mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-31 14:35:19 +00:00
Merge branch 'shadps4-emu:main' into main
This commit is contained in:
commit
c94f4468f4
@ -25,7 +25,9 @@ static bool shouldDumpPM4 = false;
|
|||||||
static u32 vblankDivider = 1;
|
static u32 vblankDivider = 1;
|
||||||
static bool vkValidation = false;
|
static bool vkValidation = false;
|
||||||
static bool vkValidationSync = false;
|
static bool vkValidationSync = false;
|
||||||
|
static bool vkValidationGpu = false;
|
||||||
static bool rdocEnable = false;
|
static bool rdocEnable = false;
|
||||||
|
static bool rdocMarkersEnable = false;
|
||||||
// Gui
|
// Gui
|
||||||
std::string settings_install_dir = "";
|
std::string settings_install_dir = "";
|
||||||
u32 main_window_geometry_x = 400;
|
u32 main_window_geometry_x = 400;
|
||||||
@ -102,6 +104,10 @@ bool isRdocEnabled() {
|
|||||||
return rdocEnable;
|
return rdocEnable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isMarkersEnabled() {
|
||||||
|
return rdocMarkersEnable;
|
||||||
|
}
|
||||||
|
|
||||||
u32 vblankDiv() {
|
u32 vblankDiv() {
|
||||||
return vblankDivider;
|
return vblankDivider;
|
||||||
}
|
}
|
||||||
@ -114,6 +120,10 @@ bool vkValidationSyncEnabled() {
|
|||||||
return vkValidationSync;
|
return vkValidationSync;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vkValidationGpuEnabled() {
|
||||||
|
return vkValidationGpu;
|
||||||
|
}
|
||||||
|
|
||||||
void setScreenWidth(u32 width) {
|
void setScreenWidth(u32 width) {
|
||||||
screenWidth = width;
|
screenWidth = width;
|
||||||
}
|
}
|
||||||
@ -319,7 +329,9 @@ void load(const std::filesystem::path& path) {
|
|||||||
gpuId = toml::find_or<int>(vk, "gpuId", -1);
|
gpuId = toml::find_or<int>(vk, "gpuId", -1);
|
||||||
vkValidation = toml::find_or<bool>(vk, "validation", false);
|
vkValidation = toml::find_or<bool>(vk, "validation", false);
|
||||||
vkValidationSync = toml::find_or<bool>(vk, "validation_sync", false);
|
vkValidationSync = toml::find_or<bool>(vk, "validation_sync", false);
|
||||||
|
vkValidationGpu = toml::find_or<bool>(vk, "validation_gpu", true);
|
||||||
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
|
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
|
||||||
|
rdocMarkersEnable = toml::find_or<bool>(vk, "rdocMarkersEnable", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.contains("Debug")) {
|
if (data.contains("Debug")) {
|
||||||
@ -394,7 +406,9 @@ void save(const std::filesystem::path& path) {
|
|||||||
data["Vulkan"]["gpuId"] = gpuId;
|
data["Vulkan"]["gpuId"] = gpuId;
|
||||||
data["Vulkan"]["validation"] = vkValidation;
|
data["Vulkan"]["validation"] = vkValidation;
|
||||||
data["Vulkan"]["validation_sync"] = vkValidationSync;
|
data["Vulkan"]["validation_sync"] = vkValidationSync;
|
||||||
|
data["Vulkan"]["validation_gpu"] = vkValidationGpu;
|
||||||
data["Vulkan"]["rdocEnable"] = rdocEnable;
|
data["Vulkan"]["rdocEnable"] = rdocEnable;
|
||||||
|
data["Vulkan"]["rdocMarkersEnable"] = rdocMarkersEnable;
|
||||||
data["Debug"]["DebugDump"] = isDebugDump;
|
data["Debug"]["DebugDump"] = isDebugDump;
|
||||||
data["LLE"]["libc"] = isLibc;
|
data["LLE"]["libc"] = isLibc;
|
||||||
data["GUI"]["theme"] = mw_themes;
|
data["GUI"]["theme"] = mw_themes;
|
||||||
|
@ -27,6 +27,7 @@ bool nullGpu();
|
|||||||
bool dumpShaders();
|
bool dumpShaders();
|
||||||
bool dumpPM4();
|
bool dumpPM4();
|
||||||
bool isRdocEnabled();
|
bool isRdocEnabled();
|
||||||
|
bool isMarkersEnabled();
|
||||||
u32 vblankDiv();
|
u32 vblankDiv();
|
||||||
|
|
||||||
void setDebugDump(bool enable);
|
void setDebugDump(bool enable);
|
||||||
@ -50,6 +51,7 @@ void setRdocEnabled(bool enable);
|
|||||||
|
|
||||||
bool vkValidationEnabled();
|
bool vkValidationEnabled();
|
||||||
bool vkValidationSyncEnabled();
|
bool vkValidationSyncEnabled();
|
||||||
|
bool vkValidationGpuEnabled();
|
||||||
|
|
||||||
// Gui
|
// Gui
|
||||||
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
|
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);
|
||||||
|
@ -956,9 +956,9 @@ int PS4_SYSV_ABI sceGnmGetGpuBlockStatus() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency() {
|
u32 PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency() {
|
||||||
LOG_DEBUG(Lib_GnmDriver, "(STUBBED) called");
|
LOG_TRACE(Lib_GnmDriver, "called");
|
||||||
return ORBIS_OK;
|
return Config::isNeoMode() ? 911'000'000 : 800'000'000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceGnmGetGpuInfoStatus() {
|
int PS4_SYSV_ABI sceGnmGetGpuInfoStatus() {
|
||||||
@ -1706,8 +1706,18 @@ int PS4_SYSV_ABI sceGnmSetupMipStatsReport() {
|
|||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceGnmSetVgtControl() {
|
s32 PS4_SYSV_ABI sceGnmSetVgtControl(u32* cmdbuf, u32 size, u32 prim_group_sz_minus_one,
|
||||||
LOG_ERROR(Lib_GnmDriver, "(STUBBED) called");
|
u32 partial_vs_wave_mode, u32 wd_switch_only_on_eop_mode) {
|
||||||
|
LOG_TRACE(Lib_GnmDriver, "called");
|
||||||
|
|
||||||
|
if (!cmdbuf || size != 3 || (prim_group_sz_minus_one >= 0x100) ||
|
||||||
|
((wd_switch_only_on_eop_mode | partial_vs_wave_mode) >= 2)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 reg_value =
|
||||||
|
((partial_vs_wave_mode & 1) << 0x10) | (prim_group_sz_minus_one & 0xffffu);
|
||||||
|
PM4CmdSetData::SetContextReg(cmdbuf, 0x2aau, reg_value); // IA_MULTI_VGT_PARAM
|
||||||
return ORBIS_OK;
|
return ORBIS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ int PS4_SYSV_ABI sceGnmGetDebugTimestamp();
|
|||||||
int PS4_SYSV_ABI sceGnmGetEqEventType();
|
int PS4_SYSV_ABI sceGnmGetEqEventType();
|
||||||
int PS4_SYSV_ABI sceGnmGetEqTimeStamp();
|
int PS4_SYSV_ABI sceGnmGetEqTimeStamp();
|
||||||
int PS4_SYSV_ABI sceGnmGetGpuBlockStatus();
|
int PS4_SYSV_ABI sceGnmGetGpuBlockStatus();
|
||||||
int PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency();
|
u32 PS4_SYSV_ABI sceGnmGetGpuCoreClockFrequency();
|
||||||
int PS4_SYSV_ABI sceGnmGetGpuInfoStatus();
|
int PS4_SYSV_ABI sceGnmGetGpuInfoStatus();
|
||||||
int PS4_SYSV_ABI sceGnmGetLastWaitedAddress();
|
int PS4_SYSV_ABI sceGnmGetLastWaitedAddress();
|
||||||
int PS4_SYSV_ABI sceGnmGetNumTcaUnits();
|
int PS4_SYSV_ABI sceGnmGetNumTcaUnits();
|
||||||
@ -161,7 +161,8 @@ int PS4_SYSV_ABI sceGnmSetResourceUserData();
|
|||||||
int PS4_SYSV_ABI sceGnmSetSpiEnableSqCounters();
|
int PS4_SYSV_ABI sceGnmSetSpiEnableSqCounters();
|
||||||
int PS4_SYSV_ABI sceGnmSetSpiEnableSqCountersForUnitInstance();
|
int PS4_SYSV_ABI sceGnmSetSpiEnableSqCountersForUnitInstance();
|
||||||
int PS4_SYSV_ABI sceGnmSetupMipStatsReport();
|
int PS4_SYSV_ABI sceGnmSetupMipStatsReport();
|
||||||
int PS4_SYSV_ABI sceGnmSetVgtControl();
|
s32 PS4_SYSV_ABI sceGnmSetVgtControl(u32* cmdbuf, u32 size, u32 prim_group_sz_minus_one,
|
||||||
|
u32 partial_vs_wave_mode, u32 wd_switch_only_on_eop_mode);
|
||||||
s32 PS4_SYSV_ABI sceGnmSetVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, u32 shader_modifier);
|
s32 PS4_SYSV_ABI sceGnmSetVsShader(u32* cmdbuf, u32 size, const u32* vs_regs, u32 shader_modifier);
|
||||||
int PS4_SYSV_ABI sceGnmSetWaveLimitMultiplier();
|
int PS4_SYSV_ABI sceGnmSetWaveLimitMultiplier();
|
||||||
int PS4_SYSV_ABI sceGnmSetWaveLimitMultipliers();
|
int PS4_SYSV_ABI sceGnmSetWaveLimitMultipliers();
|
||||||
|
@ -174,10 +174,16 @@ s32 PS4_SYSV_ABI sceKernelCreateSema(OrbisKernelSema* sem, const char* pName, u3
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelWaitSema(OrbisKernelSema sem, s32 needCount, u32* pTimeout) {
|
s32 PS4_SYSV_ABI sceKernelWaitSema(OrbisKernelSema sem, s32 needCount, u32* pTimeout) {
|
||||||
|
if (!sem) {
|
||||||
|
return ORBIS_KERNEL_ERROR_ESRCH;
|
||||||
|
}
|
||||||
return sem->Wait(true, needCount, pTimeout);
|
return sem->Wait(true, needCount, pTimeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelSignalSema(OrbisKernelSema sem, s32 signalCount) {
|
s32 PS4_SYSV_ABI sceKernelSignalSema(OrbisKernelSema sem, s32 signalCount) {
|
||||||
|
if (!sem) {
|
||||||
|
return ORBIS_KERNEL_ERROR_ESRCH;
|
||||||
|
}
|
||||||
if (!sem->Signal(signalCount)) {
|
if (!sem->Signal(signalCount)) {
|
||||||
return ORBIS_KERNEL_ERROR_EINVAL;
|
return ORBIS_KERNEL_ERROR_EINVAL;
|
||||||
}
|
}
|
||||||
@ -185,10 +191,16 @@ s32 PS4_SYSV_ABI sceKernelSignalSema(OrbisKernelSema sem, s32 signalCount) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s32 PS4_SYSV_ABI sceKernelPollSema(OrbisKernelSema sem, s32 needCount) {
|
s32 PS4_SYSV_ABI sceKernelPollSema(OrbisKernelSema sem, s32 needCount) {
|
||||||
|
if (!sem) {
|
||||||
|
return ORBIS_KERNEL_ERROR_ESRCH;
|
||||||
|
}
|
||||||
return sem->Wait(false, needCount, nullptr);
|
return sem->Wait(false, needCount, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int PS4_SYSV_ABI sceKernelCancelSema(OrbisKernelSema sem, s32 setCount, s32* pNumWaitThreads) {
|
int PS4_SYSV_ABI sceKernelCancelSema(OrbisKernelSema sem, s32 setCount, s32* pNumWaitThreads) {
|
||||||
|
if (!sem) {
|
||||||
|
return ORBIS_KERNEL_ERROR_ESRCH;
|
||||||
|
}
|
||||||
return sem->Cancel(setCount, pNumWaitThreads);
|
return sem->Cancel(setCount, pNumWaitThreads);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,19 +386,12 @@ static Id GetBufferFormatValue(EmitContext& ctx, u32 handle, Id address, u32 com
|
|||||||
if (is_signed) {
|
if (is_signed) {
|
||||||
value = ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset,
|
value = ctx.OpBitFieldSExtract(ctx.S32[1], value, comp_offset,
|
||||||
ctx.ConstU32(bit_width));
|
ctx.ConstU32(bit_width));
|
||||||
value = ctx.OpConvertSToF(ctx.F32[1], value);
|
|
||||||
} else {
|
} else {
|
||||||
value = ctx.OpBitFieldUExtract(ctx.U32[1], value, comp_offset,
|
value = ctx.OpBitFieldUExtract(ctx.U32[1], value, comp_offset,
|
||||||
ctx.ConstU32(bit_width));
|
ctx.ConstU32(bit_width));
|
||||||
value = ctx.OpConvertUToF(ctx.F32[1], value);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (is_signed) {
|
|
||||||
value = ctx.OpConvertSToF(ctx.F32[1], value);
|
|
||||||
} else {
|
|
||||||
value = ctx.OpConvertUToF(ctx.F32[1], value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
value = ctx.OpBitcast(ctx.F32[1], value);
|
||||||
return ConvertValue(ctx, value, num_format, bit_width);
|
return ConvertValue(ctx, value, num_format, bit_width);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -33,14 +33,14 @@ Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id c
|
|||||||
operands.operands);
|
operands.operands);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id bias_lc,
|
Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod,
|
||||||
Id offset) {
|
Id offset) {
|
||||||
const auto& texture = ctx.images[handle & 0xFFFF];
|
const auto& texture = ctx.images[handle & 0xFFFF];
|
||||||
const Id image = ctx.OpLoad(texture.image_type, texture.id);
|
const Id image = ctx.OpLoad(texture.image_type, texture.id);
|
||||||
const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]);
|
const Id sampler = ctx.OpLoad(ctx.sampler_type, ctx.samplers[handle >> 16]);
|
||||||
const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler);
|
const Id sampled_image = ctx.OpSampledImage(texture.sampled_type, image, sampler);
|
||||||
return ctx.OpImageSampleExplicitLod(ctx.F32[4], sampled_image, coords,
|
return ctx.OpImageSampleExplicitLod(ctx.F32[4], sampled_image, coords,
|
||||||
spv::ImageOperandsMask::Lod, ctx.ConstF32(0.f));
|
spv::ImageOperandsMask::Lod, lod);
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref,
|
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref,
|
||||||
|
@ -359,7 +359,7 @@ Id EmitConvertU32U16(EmitContext& ctx, Id value);
|
|||||||
|
|
||||||
Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id bias_lc,
|
Id EmitImageSampleImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id bias_lc,
|
||||||
Id offset);
|
Id offset);
|
||||||
Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id bias_lc,
|
Id EmitImageSampleExplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id lod,
|
||||||
Id offset);
|
Id offset);
|
||||||
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref,
|
Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, u32 handle, Id coords, Id dref,
|
||||||
Id bias_lc, const IR::Value& offset);
|
Id bias_lc, const IR::Value& offset);
|
||||||
|
@ -376,9 +376,11 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
// We have found this pattern. Build the sharp.
|
// We have found this pattern. Build the sharp.
|
||||||
std::array<u64, 2> buffer;
|
std::array<u32, 4> buffer;
|
||||||
buffer[0] = info.pgm_base + p0->Arg(0).U32() + p0->Arg(1).U32();
|
buffer[0] = info.pgm_base + p0->Arg(0).U32() + p0->Arg(1).U32();
|
||||||
buffer[1] = handle->Arg(2).U32() | handle->Arg(3).U64() << 32;
|
buffer[1] = 0;
|
||||||
|
buffer[2] = handle->Arg(2).U32();
|
||||||
|
buffer[3] = handle->Arg(3).U32();
|
||||||
cbuf = std::bit_cast<AmdGpu::Buffer>(buffer);
|
cbuf = std::bit_cast<AmdGpu::Buffer>(buffer);
|
||||||
// Assign a binding to this sharp.
|
// Assign a binding to this sharp.
|
||||||
return descriptors.Add(BufferResource{
|
return descriptors.Add(BufferResource{
|
||||||
|
@ -116,7 +116,7 @@ struct PushData {
|
|||||||
std::array<u8, 32> buf_offsets;
|
std::array<u8, 32> buf_offsets;
|
||||||
|
|
||||||
void AddOffset(u32 binding, u32 offset) {
|
void AddOffset(u32 binding, u32 offset) {
|
||||||
ASSERT(offset < 64 && binding < 32);
|
ASSERT(offset < 256 && binding < buf_offsets.size());
|
||||||
buf_offsets[binding] = offset;
|
buf_offsets[binding] = offset;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -180,6 +180,17 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||||||
Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxFlip);
|
Platform::IrqC::Instance()->Signal(Platform::InterruptId::GfxFlip);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case PM4CmdNop::PayloadType::DebugMarkerPush: {
|
||||||
|
const auto marker_sz = nop->header.count.Value() * 2;
|
||||||
|
const std::string_view label{reinterpret_cast<const char*>(&nop->data_block[1]),
|
||||||
|
marker_sz};
|
||||||
|
rasterizer->ScopeMarkerBegin(label);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case PM4CmdNop::PayloadType::DebugMarkerPop: {
|
||||||
|
rasterizer->ScopeMarkerEnd();
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -226,7 +237,7 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||||||
ASSERT(col_buf_id < NumColorBuffers);
|
ASSERT(col_buf_id < NumColorBuffers);
|
||||||
|
|
||||||
const auto nop_offset = header->type3.count;
|
const auto nop_offset = header->type3.count;
|
||||||
if (nop_offset == 0x0e || nop_offset == 0x0d) {
|
if (nop_offset == 0x0e || nop_offset == 0x0d || nop_offset == 0x0b) {
|
||||||
ASSERT_MSG(payload[nop_offset] == 0xc0001000,
|
ASSERT_MSG(payload[nop_offset] == 0xc0001000,
|
||||||
"NOP hint is missing in CB setup sequence");
|
"NOP hint is missing in CB setup sequence");
|
||||||
last_cb_extent[col_buf_id].raw = payload[nop_offset + 1];
|
last_cb_extent[col_buf_id].raw = payload[nop_offset + 1];
|
||||||
@ -295,8 +306,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||||||
regs.num_indices = draw_index->index_count;
|
regs.num_indices = draw_index->index_count;
|
||||||
regs.draw_initiator = draw_index->draw_initiator;
|
regs.draw_initiator = draw_index->draw_initiator;
|
||||||
if (rasterizer) {
|
if (rasterizer) {
|
||||||
rasterizer->ScopeMarkerBegin(
|
const auto cmd_address = reinterpret_cast<const void*>(header);
|
||||||
fmt::format("dcb:{}:DrawIndex2", reinterpret_cast<const void*>(dcb.data())));
|
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndex2", cmd_address));
|
||||||
|
rasterizer->Breadcrumb(u64(cmd_address));
|
||||||
rasterizer->Draw(true);
|
rasterizer->Draw(true);
|
||||||
rasterizer->ScopeMarkerEnd();
|
rasterizer->ScopeMarkerEnd();
|
||||||
}
|
}
|
||||||
@ -308,8 +320,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||||||
regs.num_indices = draw_index_off->index_count;
|
regs.num_indices = draw_index_off->index_count;
|
||||||
regs.draw_initiator = draw_index_off->draw_initiator;
|
regs.draw_initiator = draw_index_off->draw_initiator;
|
||||||
if (rasterizer) {
|
if (rasterizer) {
|
||||||
rasterizer->ScopeMarkerBegin(fmt::format(
|
const auto cmd_address = reinterpret_cast<const void*>(header);
|
||||||
"dcb:{}:DrawIndexOffset2", reinterpret_cast<const void*>(dcb.data())));
|
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexOffset2", cmd_address));
|
||||||
|
rasterizer->Breadcrumb(u64(cmd_address));
|
||||||
rasterizer->Draw(true, draw_index_off->index_offset);
|
rasterizer->Draw(true, draw_index_off->index_offset);
|
||||||
rasterizer->ScopeMarkerEnd();
|
rasterizer->ScopeMarkerEnd();
|
||||||
}
|
}
|
||||||
@ -320,8 +333,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||||||
regs.num_indices = draw_index->index_count;
|
regs.num_indices = draw_index->index_count;
|
||||||
regs.draw_initiator = draw_index->draw_initiator;
|
regs.draw_initiator = draw_index->draw_initiator;
|
||||||
if (rasterizer) {
|
if (rasterizer) {
|
||||||
rasterizer->ScopeMarkerBegin(
|
const auto cmd_address = reinterpret_cast<const void*>(header);
|
||||||
fmt::format("dcb:{}:DrawIndexAuto", reinterpret_cast<const void*>(dcb.data())));
|
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:DrawIndexAuto", cmd_address));
|
||||||
|
rasterizer->Breadcrumb(u64(cmd_address));
|
||||||
rasterizer->Draw(false);
|
rasterizer->Draw(false);
|
||||||
rasterizer->ScopeMarkerEnd();
|
rasterizer->ScopeMarkerEnd();
|
||||||
}
|
}
|
||||||
@ -334,8 +348,9 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
|
|||||||
regs.cs_program.dim_z = dispatch_direct->dim_z;
|
regs.cs_program.dim_z = dispatch_direct->dim_z;
|
||||||
regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator;
|
regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator;
|
||||||
if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) {
|
if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) {
|
||||||
rasterizer->ScopeMarkerBegin(
|
const auto cmd_address = reinterpret_cast<const void*>(header);
|
||||||
fmt::format("dcb:{}:Dispatch", reinterpret_cast<const void*>(dcb.data())));
|
rasterizer->ScopeMarkerBegin(fmt::format("dcb:{}:Dispatch", cmd_address));
|
||||||
|
rasterizer->Breadcrumb(u64(cmd_address));
|
||||||
rasterizer->DispatchDirect();
|
rasterizer->DispatchDirect();
|
||||||
rasterizer->ScopeMarkerEnd();
|
rasterizer->ScopeMarkerEnd();
|
||||||
}
|
}
|
||||||
@ -486,8 +501,9 @@ Liverpool::Task Liverpool::ProcessCompute(std::span<const u32> acb, int vqid) {
|
|||||||
regs.cs_program.dim_z = dispatch_direct->dim_z;
|
regs.cs_program.dim_z = dispatch_direct->dim_z;
|
||||||
regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator;
|
regs.cs_program.dispatch_initiator = dispatch_direct->dispatch_initiator;
|
||||||
if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) {
|
if (rasterizer && (regs.cs_program.dispatch_initiator & 1)) {
|
||||||
rasterizer->ScopeMarkerBegin(fmt::format(
|
const auto cmd_address = reinterpret_cast<const void*>(header);
|
||||||
"acb[{}]:{}:Dispatch", vqid, reinterpret_cast<const void*>(acb.data())));
|
rasterizer->ScopeMarkerBegin(fmt::format("acb[{}]:{}:Dispatch", vqid, cmd_address));
|
||||||
|
rasterizer->Breadcrumb(u64(cmd_address));
|
||||||
rasterizer->DispatchDirect();
|
rasterizer->DispatchDirect();
|
||||||
rasterizer->ScopeMarkerEnd();
|
rasterizer->ScopeMarkerEnd();
|
||||||
}
|
}
|
||||||
|
@ -766,7 +766,8 @@ struct Liverpool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TilingMode GetTilingMode() const {
|
TilingMode GetTilingMode() const {
|
||||||
return attrib.tile_mode_index;
|
return info.linear_general ? TilingMode::Display_Linear
|
||||||
|
: attrib.tile_mode_index.Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsTiled() const {
|
bool IsTiled() const {
|
||||||
|
@ -282,6 +282,13 @@ enum class InterruptSelect : u32 {
|
|||||||
IrqUndocumented = 3,
|
IrqUndocumented = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static u64 GetGpuClock64() {
|
||||||
|
auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
auto duration = now.time_since_epoch();
|
||||||
|
auto ticks = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
|
||||||
|
return static_cast<u64>(ticks);
|
||||||
|
}
|
||||||
|
|
||||||
struct PM4CmdEventWriteEop {
|
struct PM4CmdEventWriteEop {
|
||||||
PM4Type3Header header;
|
PM4Type3Header header;
|
||||||
union {
|
union {
|
||||||
@ -325,6 +332,10 @@ struct PM4CmdEventWriteEop {
|
|||||||
*Address<u64>() = DataQWord();
|
*Address<u64>() = DataQWord();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DataSelect::GpuClock64: {
|
||||||
|
*Address<u64>() = GetGpuClock64();
|
||||||
|
break;
|
||||||
|
}
|
||||||
case DataSelect::PerfCounter: {
|
case DataSelect::PerfCounter: {
|
||||||
*Address<u64>() = Common::FencedRDTSC();
|
*Address<u64>() = Common::FencedRDTSC();
|
||||||
break;
|
break;
|
||||||
@ -652,13 +663,6 @@ struct PM4CmdReleaseMem {
|
|||||||
return data_lo | u64(data_hi) << 32;
|
return data_lo | u64(data_hi) << 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GetGpuClock64() const {
|
|
||||||
auto now = std::chrono::high_resolution_clock::now();
|
|
||||||
auto duration = now.time_since_epoch();
|
|
||||||
auto ticks = std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
|
|
||||||
return static_cast<uint64_t>(ticks);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SignalFence(Platform::InterruptId irq_id) const {
|
void SignalFence(Platform::InterruptId irq_id) const {
|
||||||
switch (data_sel.Value()) {
|
switch (data_sel.Value()) {
|
||||||
case DataSelect::Data32Low: {
|
case DataSelect::Data32Low: {
|
||||||
|
@ -41,6 +41,7 @@ enum class PM4ItOpcode : u32 {
|
|||||||
CondIndirectBuffer = 0x3F,
|
CondIndirectBuffer = 0x3F,
|
||||||
CopyData = 0x40,
|
CopyData = 0x40,
|
||||||
CommandProcessorDma = 0x41,
|
CommandProcessorDma = 0x41,
|
||||||
|
PfpSyncMe = 0x42,
|
||||||
SurfaceSync = 0x43,
|
SurfaceSync = 0x43,
|
||||||
CondWrite = 0x45,
|
CondWrite = 0x45,
|
||||||
EventWrite = 0x46,
|
EventWrite = 0x46,
|
||||||
|
@ -106,10 +106,8 @@ Buffer::Buffer(const Vulkan::Instance& instance_, MemoryUsage usage_, VAddr cpu_
|
|||||||
VmaAllocationInfo alloc_info{};
|
VmaAllocationInfo alloc_info{};
|
||||||
buffer.Create(buffer_ci, usage, &alloc_info);
|
buffer.Create(buffer_ci, usage, &alloc_info);
|
||||||
|
|
||||||
if (instance->HasDebuggingToolAttached()) {
|
const auto device = instance->GetDevice();
|
||||||
const auto device = instance->GetDevice();
|
Vulkan::SetObjectName(device, Handle(), "Buffer {:#x}:{:#x}", cpu_addr, size_bytes);
|
||||||
Vulkan::SetObjectName(device, Handle(), "Buffer {:#x} {} KiB", cpu_addr, size_bytes / 1024);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map it if it is host visible.
|
// Map it if it is host visible.
|
||||||
VkMemoryPropertyFlags property_flags{};
|
VkMemoryPropertyFlags property_flags{};
|
||||||
@ -152,10 +150,8 @@ StreamBuffer::StreamBuffer(const Vulkan::Instance& instance, Vulkan::Scheduler&
|
|||||||
ReserveWatches(current_watches, WATCHES_INITIAL_RESERVE);
|
ReserveWatches(current_watches, WATCHES_INITIAL_RESERVE);
|
||||||
ReserveWatches(previous_watches, WATCHES_INITIAL_RESERVE);
|
ReserveWatches(previous_watches, WATCHES_INITIAL_RESERVE);
|
||||||
const auto device = instance.GetDevice();
|
const auto device = instance.GetDevice();
|
||||||
if (instance.HasDebuggingToolAttached()) {
|
Vulkan::SetObjectName(device, Handle(), "StreamBuffer({}):{:#x}", BufferTypeName(usage),
|
||||||
Vulkan::SetObjectName(device, Handle(), "StreamBuffer({}): {} KiB", BufferTypeName(usage),
|
size_bytes);
|
||||||
size_bytes / 1024);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<u8*, u64> StreamBuffer::Map(u64 size, u64 alignment) {
|
std::pair<u8*, u64> StreamBuffer::Map(u64 size, u64 alignment) {
|
||||||
|
@ -146,6 +146,10 @@ public:
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 GetFreeSize() const {
|
||||||
|
return size_bytes - offset - mapped_size;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct Watch {
|
struct Watch {
|
||||||
u64 tick{};
|
u64 tick{};
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <fmt/ranges.h>
|
#include <fmt/ranges.h>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/config.h"
|
||||||
#include "sdl_window.h"
|
#include "sdl_window.h"
|
||||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
@ -213,6 +214,13 @@ bool Instance::CreateDevice() {
|
|||||||
add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
|
add_extension(VK_KHR_MAINTENANCE_4_EXTENSION_NAME);
|
||||||
add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
|
add_extension(VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME);
|
||||||
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
|
add_extension(VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME);
|
||||||
|
const bool has_sync2 = add_extension(VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME);
|
||||||
|
|
||||||
|
if (has_sync2) {
|
||||||
|
has_nv_checkpoints = Config::isMarkersEnabled()
|
||||||
|
? add_extension(VK_NV_DEVICE_DIAGNOSTIC_CHECKPOINTS_EXTENSION_NAME)
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
|
||||||
const auto family_properties = physical_device.getQueueFamilyProperties();
|
const auto family_properties = physical_device.getQueueFamilyProperties();
|
||||||
if (family_properties.empty()) {
|
if (family_properties.empty()) {
|
||||||
@ -308,6 +316,9 @@ bool Instance::CreateDevice() {
|
|||||||
vk::PhysicalDeviceRobustness2FeaturesEXT{
|
vk::PhysicalDeviceRobustness2FeaturesEXT{
|
||||||
.nullDescriptor = true,
|
.nullDescriptor = true,
|
||||||
},
|
},
|
||||||
|
vk::PhysicalDeviceSynchronization2Features{
|
||||||
|
.synchronization2 = has_sync2,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!color_write_en) {
|
if (!color_write_en) {
|
||||||
|
@ -88,6 +88,10 @@ public:
|
|||||||
return profiler_context;
|
return profiler_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasNvCheckpoints() const {
|
||||||
|
return has_nv_checkpoints;
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true when a known debugging tool is attached.
|
/// Returns true when a known debugging tool is attached.
|
||||||
bool HasDebuggingToolAttached() const {
|
bool HasDebuggingToolAttached() const {
|
||||||
return has_renderdoc || has_nsight_graphics;
|
return has_renderdoc || has_nsight_graphics;
|
||||||
@ -259,6 +263,7 @@ private:
|
|||||||
bool debug_utils_supported{};
|
bool debug_utils_supported{};
|
||||||
bool has_nsight_graphics{};
|
bool has_nsight_graphics{};
|
||||||
bool has_renderdoc{};
|
bool has_renderdoc{};
|
||||||
|
bool has_nv_checkpoints{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -221,12 +221,61 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT
|
|||||||
|
|
||||||
vk::Bool32 enable_sync =
|
vk::Bool32 enable_sync =
|
||||||
enable_validation && Config::vkValidationSyncEnabled() ? vk::True : vk::False;
|
enable_validation && Config::vkValidationSyncEnabled() ? vk::True : vk::False;
|
||||||
vk::LayerSettingEXT layer_set = {
|
vk::Bool32 enable_gpuav =
|
||||||
.pLayerName = VALIDATION_LAYER_NAME,
|
enable_validation && Config::vkValidationSyncEnabled() ? vk::True : vk::False;
|
||||||
.pSettingName = "validate_sync",
|
const char* gpuav_mode = enable_validation && Config::vkValidationGpuEnabled()
|
||||||
.type = vk::LayerSettingTypeEXT::eBool32,
|
? "GPU_BASED_GPU_ASSISTED"
|
||||||
.valueCount = 1,
|
: "GPU_BASED_NONE";
|
||||||
.pValues = &enable_sync,
|
const std::array layer_setings = {
|
||||||
|
vk::LayerSettingEXT{
|
||||||
|
.pLayerName = VALIDATION_LAYER_NAME,
|
||||||
|
.pSettingName = "validate_sync",
|
||||||
|
.type = vk::LayerSettingTypeEXT::eBool32,
|
||||||
|
.valueCount = 1,
|
||||||
|
.pValues = &enable_sync,
|
||||||
|
},
|
||||||
|
vk::LayerSettingEXT{
|
||||||
|
.pLayerName = VALIDATION_LAYER_NAME,
|
||||||
|
.pSettingName = "sync_queue_submit",
|
||||||
|
.type = vk::LayerSettingTypeEXT::eBool32,
|
||||||
|
.valueCount = 1,
|
||||||
|
.pValues = &enable_sync,
|
||||||
|
},
|
||||||
|
vk::LayerSettingEXT{
|
||||||
|
.pLayerName = VALIDATION_LAYER_NAME,
|
||||||
|
.pSettingName = "validate_gpu_based",
|
||||||
|
.type = vk::LayerSettingTypeEXT::eString,
|
||||||
|
.valueCount = 1,
|
||||||
|
.pValues = &gpuav_mode,
|
||||||
|
},
|
||||||
|
vk::LayerSettingEXT{
|
||||||
|
.pLayerName = VALIDATION_LAYER_NAME,
|
||||||
|
.pSettingName = "gpuav_reserve_binding_slot",
|
||||||
|
.type = vk::LayerSettingTypeEXT::eBool32,
|
||||||
|
.valueCount = 1,
|
||||||
|
.pValues = &enable_gpuav,
|
||||||
|
},
|
||||||
|
vk::LayerSettingEXT{
|
||||||
|
.pLayerName = VALIDATION_LAYER_NAME,
|
||||||
|
.pSettingName = "gpuav_descriptor_checks",
|
||||||
|
.type = vk::LayerSettingTypeEXT::eBool32,
|
||||||
|
.valueCount = 1,
|
||||||
|
.pValues = &enable_gpuav,
|
||||||
|
},
|
||||||
|
vk::LayerSettingEXT{
|
||||||
|
.pLayerName = VALIDATION_LAYER_NAME,
|
||||||
|
.pSettingName = "gpuav_validate_indirect_buffer",
|
||||||
|
.type = vk::LayerSettingTypeEXT::eBool32,
|
||||||
|
.valueCount = 1,
|
||||||
|
.pValues = &enable_gpuav,
|
||||||
|
},
|
||||||
|
vk::LayerSettingEXT{
|
||||||
|
.pLayerName = VALIDATION_LAYER_NAME,
|
||||||
|
.pSettingName = "gpuav_buffer_copies",
|
||||||
|
.type = vk::LayerSettingTypeEXT::eBool32,
|
||||||
|
.valueCount = 1,
|
||||||
|
.pValues = &enable_gpuav,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
vk::StructureChain<vk::InstanceCreateInfo, vk::LayerSettingsCreateInfoEXT> instance_ci_chain = {
|
vk::StructureChain<vk::InstanceCreateInfo, vk::LayerSettingsCreateInfoEXT> instance_ci_chain = {
|
||||||
@ -238,8 +287,8 @@ vk::UniqueInstance CreateInstance(vk::DynamicLoader& dl, Frontend::WindowSystemT
|
|||||||
.ppEnabledExtensionNames = extensions.data(),
|
.ppEnabledExtensionNames = extensions.data(),
|
||||||
},
|
},
|
||||||
vk::LayerSettingsCreateInfoEXT{
|
vk::LayerSettingsCreateInfoEXT{
|
||||||
.settingCount = 1,
|
.settingCount = layer_setings.size(),
|
||||||
.pSettings = &layer_set,
|
.pSettings = layer_setings.data(),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -152,7 +152,8 @@ void Rasterizer::BeginRendering() {
|
|||||||
.stencil = regs.stencil_clear}},
|
.stencil = regs.stencil_clear}},
|
||||||
};
|
};
|
||||||
texture_cache.TouchMeta(htile_address, false);
|
texture_cache.TouchMeta(htile_address, false);
|
||||||
state.num_depth_attachments++;
|
state.has_depth = true;
|
||||||
|
state.has_stencil = image.info.usage.stencil;
|
||||||
}
|
}
|
||||||
scheduler.BeginRendering(state);
|
scheduler.BeginRendering(state);
|
||||||
}
|
}
|
||||||
@ -230,16 +231,42 @@ void Rasterizer::UpdateDepthStencilState() {
|
|||||||
cmdbuf.setDepthBoundsTestEnable(depth.depth_bounds_enable);
|
cmdbuf.setDepthBoundsTestEnable(depth.depth_bounds_enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::ScopeMarkerBegin(const std::string& str) {
|
void Rasterizer::ScopeMarkerBegin(const std::string_view& str) {
|
||||||
|
if (!Config::isMarkersEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
cmdbuf.beginDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{
|
cmdbuf.beginDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{
|
||||||
.pLabelName = str.c_str(),
|
.pLabelName = str.data(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Rasterizer::ScopeMarkerEnd() {
|
void Rasterizer::ScopeMarkerEnd() {
|
||||||
|
if (!Config::isMarkersEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const auto cmdbuf = scheduler.CommandBuffer();
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
cmdbuf.endDebugUtilsLabelEXT();
|
cmdbuf.endDebugUtilsLabelEXT();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Rasterizer::ScopedMarkerInsert(const std::string_view& str) {
|
||||||
|
if (!Config::isMarkersEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto cmdbuf = scheduler.CommandBuffer();
|
||||||
|
cmdbuf.insertDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{
|
||||||
|
.pLabelName = str.data(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rasterizer::Breadcrumb(u64 id) {
|
||||||
|
if (!instance.HasNvCheckpoints()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scheduler.CommandBuffer().setCheckpointNV(id);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Vulkan
|
} // namespace Vulkan
|
||||||
|
@ -35,8 +35,10 @@ public:
|
|||||||
|
|
||||||
void DispatchDirect();
|
void DispatchDirect();
|
||||||
|
|
||||||
void ScopeMarkerBegin(const std::string& str);
|
void ScopeMarkerBegin(const std::string_view& str);
|
||||||
void ScopeMarkerEnd();
|
void ScopeMarkerEnd();
|
||||||
|
void ScopedMarkerInsert(const std::string_view& str);
|
||||||
|
void Breadcrumb(u64 id);
|
||||||
|
|
||||||
void InvalidateMemory(VAddr addr, u64 size);
|
void InvalidateMemory(VAddr addr, u64 size);
|
||||||
void MapMemory(VAddr addr, u64 size);
|
void MapMemory(VAddr addr, u64 size);
|
||||||
|
@ -38,8 +38,7 @@ void Scheduler::BeginRendering(const RenderState& new_state) {
|
|||||||
.layerCount = 1,
|
.layerCount = 1,
|
||||||
.colorAttachmentCount = render_state.num_color_attachments,
|
.colorAttachmentCount = render_state.num_color_attachments,
|
||||||
.pColorAttachments = render_state.color_attachments.data(),
|
.pColorAttachments = render_state.color_attachments.data(),
|
||||||
.pDepthAttachment =
|
.pDepthAttachment = render_state.has_depth ? &render_state.depth_attachment : nullptr,
|
||||||
render_state.num_depth_attachments ? &render_state.depth_attachment : nullptr,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
current_cmdbuf.beginRendering(rendering_info);
|
current_cmdbuf.beginRendering(rendering_info);
|
||||||
@ -50,6 +49,8 @@ void Scheduler::EndRendering() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
is_rendering = false;
|
is_rendering = false;
|
||||||
|
current_cmdbuf.endRendering();
|
||||||
|
|
||||||
boost::container::static_vector<vk::ImageMemoryBarrier, 9> barriers;
|
boost::container::static_vector<vk::ImageMemoryBarrier, 9> barriers;
|
||||||
for (size_t i = 0; i < render_state.num_color_attachments; ++i) {
|
for (size_t i = 0; i < render_state.num_color_attachments; ++i) {
|
||||||
barriers.push_back(vk::ImageMemoryBarrier{
|
barriers.push_back(vk::ImageMemoryBarrier{
|
||||||
@ -70,10 +71,35 @@ void Scheduler::EndRendering() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
current_cmdbuf.endRendering();
|
if (render_state.has_depth) {
|
||||||
|
barriers.push_back(vk::ImageMemoryBarrier{
|
||||||
|
.srcAccessMask = vk::AccessFlagBits::eDepthStencilAttachmentWrite,
|
||||||
|
.dstAccessMask = vk::AccessFlagBits::eShaderRead | vk::AccessFlagBits::eShaderWrite,
|
||||||
|
.oldLayout = render_state.depth_attachment.imageLayout,
|
||||||
|
.newLayout = render_state.depth_attachment.imageLayout,
|
||||||
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
|
.image = render_state.depth_image,
|
||||||
|
.subresourceRange =
|
||||||
|
{
|
||||||
|
.aspectMask = vk::ImageAspectFlagBits::eDepth |
|
||||||
|
(render_state.has_stencil ? vk::ImageAspectFlagBits::eStencil
|
||||||
|
: vk::ImageAspectFlagBits::eNone),
|
||||||
|
.baseMipLevel = 0,
|
||||||
|
.levelCount = VK_REMAINING_MIP_LEVELS,
|
||||||
|
.baseArrayLayer = 0,
|
||||||
|
.layerCount = VK_REMAINING_ARRAY_LAYERS,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (!barriers.empty()) {
|
if (!barriers.empty()) {
|
||||||
current_cmdbuf.pipelineBarrier(vk::PipelineStageFlagBits::eColorAttachmentOutput,
|
const auto src_stages =
|
||||||
vk::PipelineStageFlagBits::eFragmentShader,
|
vk::PipelineStageFlagBits::eColorAttachmentOutput |
|
||||||
|
(render_state.has_depth ? vk::PipelineStageFlagBits::eLateFragmentTests |
|
||||||
|
vk::PipelineStageFlagBits::eEarlyFragmentTests
|
||||||
|
: vk::PipelineStageFlagBits::eNone);
|
||||||
|
current_cmdbuf.pipelineBarrier(src_stages, vk::PipelineStageFlagBits::eFragmentShader,
|
||||||
vk::DependencyFlagBits::eByRegion, {}, {}, barriers);
|
vk::DependencyFlagBits::eByRegion, {}, {}, barriers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,6 +184,13 @@ void Scheduler::SubmitExecution(SubmitInfo& info) {
|
|||||||
try {
|
try {
|
||||||
instance.GetGraphicsQueue().submit(submit_info, info.fence);
|
instance.GetGraphicsQueue().submit(submit_info, info.fence);
|
||||||
} catch (vk::DeviceLostError& err) {
|
} catch (vk::DeviceLostError& err) {
|
||||||
|
if (instance.HasNvCheckpoints()) {
|
||||||
|
const auto checkpoint_data = instance.GetGraphicsQueue().getCheckpointData2NV();
|
||||||
|
for (const auto& cp : checkpoint_data) {
|
||||||
|
LOG_CRITICAL(Render_Vulkan, "{}: {:#x}", vk::to_string(cp.stage),
|
||||||
|
reinterpret_cast<u64>(cp.pCheckpointMarker));
|
||||||
|
}
|
||||||
|
}
|
||||||
UNREACHABLE_MSG("Device lost during submit: {}", err.what());
|
UNREACHABLE_MSG("Device lost during submit: {}", err.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,8 @@ struct RenderState {
|
|||||||
vk::RenderingAttachmentInfo depth_attachment{};
|
vk::RenderingAttachmentInfo depth_attachment{};
|
||||||
vk::Image depth_image{};
|
vk::Image depth_image{};
|
||||||
u32 num_color_attachments{};
|
u32 num_color_attachments{};
|
||||||
u32 num_depth_attachments{};
|
bool has_depth{};
|
||||||
|
bool has_stencil{};
|
||||||
u32 width = std::numeric_limits<u32>::max();
|
u32 width = std::numeric_limits<u32>::max();
|
||||||
u32 height = std::numeric_limits<u32>::max();
|
u32 height = std::numeric_limits<u32>::max();
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/config.h"
|
||||||
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
#include "video_core/renderer_vulkan/liverpool_to_vk.h"
|
||||||
#include "video_core/renderer_vulkan/vk_instance.h"
|
#include "video_core/renderer_vulkan/vk_instance.h"
|
||||||
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
#include "video_core/renderer_vulkan/vk_scheduler.h"
|
||||||
@ -154,6 +155,9 @@ Image::Image(const Vulkan::Instance& instance_, Vulkan::Scheduler& scheduler_,
|
|||||||
};
|
};
|
||||||
|
|
||||||
image.Create(image_ci);
|
image.Create(image_ci);
|
||||||
|
|
||||||
|
Vulkan::SetObjectName(instance->GetDevice(), (vk::Image)image, "Image {:#x}:{:#x}",
|
||||||
|
info.guest_address, info.guest_size_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Image::Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask,
|
void Image::Transit(vk::ImageLayout dst_layout, vk::Flags<vk::AccessFlagBits> dst_mask,
|
||||||
|
@ -189,6 +189,8 @@ ImageInfo::ImageInfo(const AmdGpu::Liverpool::DepthBuffer& buffer, u32 num_slice
|
|||||||
resources.layers = num_slices;
|
resources.layers = num_slices;
|
||||||
meta_info.htile_addr = buffer.z_info.tile_surface_en ? htile_address : 0;
|
meta_info.htile_addr = buffer.z_info.tile_surface_en ? htile_address : 0;
|
||||||
usage.depth_target = true;
|
usage.depth_target = true;
|
||||||
|
usage.stencil =
|
||||||
|
buffer.stencil_info.format != AmdGpu::Liverpool::DepthBuffer::StencilFormat::Invalid;
|
||||||
|
|
||||||
guest_address = buffer.Address();
|
guest_address = buffer.Address();
|
||||||
const auto depth_slice_sz = buffer.GetDepthSliceSize();
|
const auto depth_slice_sz = buffer.GetDepthSliceSize();
|
||||||
@ -260,7 +262,7 @@ ImageInfo::ImageInfo(const AmdGpu::Image& image) noexcept {
|
|||||||
case AmdGpu::TilingMode::Display_MacroTiled:
|
case AmdGpu::TilingMode::Display_MacroTiled:
|
||||||
case AmdGpu::TilingMode::Texture_MacroTiled:
|
case AmdGpu::TilingMode::Texture_MacroTiled:
|
||||||
case AmdGpu::TilingMode::Depth_MacroTiled: {
|
case AmdGpu::TilingMode::Depth_MacroTiled: {
|
||||||
// ASSERT(!props.is_cube && !props.is_block);
|
ASSERT(!props.is_block);
|
||||||
ASSERT(num_samples == 1);
|
ASSERT(num_samples == 1);
|
||||||
std::tie(mip_info.pitch, mip_info.size) =
|
std::tie(mip_info.pitch, mip_info.size) =
|
||||||
ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, image.tiling_index);
|
ImageSizeMacroTiled(mip_w, mip_h, bpp, num_samples, image.tiling_index);
|
||||||
|
@ -92,6 +92,8 @@ ImageViewInfo::ImageViewInfo(const AmdGpu::Liverpool::ColorBuffer& col_buffer,
|
|||||||
bool is_vo_surface) noexcept {
|
bool is_vo_surface) noexcept {
|
||||||
const auto base_format =
|
const auto base_format =
|
||||||
Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.info.format, col_buffer.NumFormat());
|
Vulkan::LiverpoolToVK::SurfaceFormat(col_buffer.info.format, col_buffer.NumFormat());
|
||||||
|
range.base.layer = col_buffer.view.slice_start;
|
||||||
|
range.extent.layers = col_buffer.NumSlices();
|
||||||
format = Vulkan::LiverpoolToVK::AdjustColorBufferFormat(
|
format = Vulkan::LiverpoolToVK::AdjustColorBufferFormat(
|
||||||
base_format, col_buffer.info.comp_swap.Value(), is_vo_surface);
|
base_format, col_buffer.info.comp_swap.Value(), is_vo_surface);
|
||||||
}
|
}
|
||||||
|
@ -194,6 +194,7 @@ vk::Format DemoteImageFormatForDetiling(vk::Format format) {
|
|||||||
case vk::Format::eR32G32Sfloat:
|
case vk::Format::eR32G32Sfloat:
|
||||||
case vk::Format::eR32G32Uint:
|
case vk::Format::eR32G32Uint:
|
||||||
case vk::Format::eR16G16B16A16Unorm:
|
case vk::Format::eR16G16B16A16Unorm:
|
||||||
|
case vk::Format::eR16G16B16A16Sfloat:
|
||||||
return vk::Format::eR32G32Uint;
|
return vk::Format::eR32G32Uint;
|
||||||
case vk::Format::eBc2SrgbBlock:
|
case vk::Format::eBc2SrgbBlock:
|
||||||
case vk::Format::eBc2UnormBlock:
|
case vk::Format::eBc2UnormBlock:
|
||||||
@ -397,7 +398,7 @@ std::optional<vk::Buffer> TileManager::TryDetile(Image& image) {
|
|||||||
const u32 image_size = image.info.guest_size_bytes;
|
const u32 image_size = image.info.guest_size_bytes;
|
||||||
const auto [in_buffer, in_offset] = [&] -> std::pair<vk::Buffer, u32> {
|
const auto [in_buffer, in_offset] = [&] -> std::pair<vk::Buffer, u32> {
|
||||||
// Use stream buffer for smaller textures.
|
// Use stream buffer for smaller textures.
|
||||||
if (image_size <= StreamBufferSize) {
|
if (image_size <= stream_buffer.GetFreeSize()) {
|
||||||
u32 offset = stream_buffer.Copy(image.info.guest_address, image_size);
|
u32 offset = stream_buffer.Copy(image.info.guest_address, image_size);
|
||||||
return {stream_buffer.Handle(), offset};
|
return {stream_buffer.Handle(), offset};
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user