mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
fix regression 9f83fd5f0c
This commit is contained in:
@@ -1284,10 +1284,10 @@ void RenderExecutor::DrawIndex(uint64_t submit_id, CommandBuffer& buffer,
|
|||||||
: ResolveDrawOffsets(ucfg.GetIndexOffset(), state.vertex_info[0]);
|
: ResolveDrawOffsets(ucfg.GetIndexOffset(), state.vertex_info[0]);
|
||||||
|
|
||||||
DrawEmitInfo emit {};
|
DrawEmitInfo emit {};
|
||||||
// Native mesh prologs consume the offsets written to the packet's user SGPRs.
|
// Native fetches consume the patched SGPRs; rewritten fetches need Vulkan offsets.
|
||||||
const bool mesh_indirect = indirect && state.vertex_info[0].logical_stage == ShaderType::Mesh;
|
const bool native_indirect = indirect && !state.vertex_info[0].fetch_embedded;
|
||||||
emit.vertex_offset = mesh_indirect ? 0 : vertex_offset + args.base_vertex;
|
emit.vertex_offset = native_indirect ? 0 : vertex_offset + args.base_vertex;
|
||||||
emit.first_instance = mesh_indirect ? 0 : instance_offset;
|
emit.first_instance = native_indirect ? 0 : instance_offset;
|
||||||
|
|
||||||
ExecutePreparedDraw(submit_id, buffer, draw, state, topology, emit, index_source,
|
ExecutePreparedDraw(submit_id, buffer, draw, state, topology, emit, index_source,
|
||||||
primitive_restart);
|
primitive_restart);
|
||||||
@@ -1375,10 +1375,10 @@ void RenderExecutor::DrawAuto(uint64_t submit_id, CommandBuffer& buffer, const D
|
|||||||
indirect ? std::pair<int32_t, uint32_t> {0, args.first_instance}
|
indirect ? std::pair<int32_t, uint32_t> {0, args.first_instance}
|
||||||
: ResolveDrawOffsets(ucfg.GetIndexOffset(), state.vertex_info[0]);
|
: ResolveDrawOffsets(ucfg.GetIndexOffset(), state.vertex_info[0]);
|
||||||
DrawEmitInfo emit {};
|
DrawEmitInfo emit {};
|
||||||
const bool mesh_indirect = indirect && state.vertex_info[0].logical_stage == ShaderType::Mesh;
|
const bool native_indirect = indirect && !state.vertex_info[0].fetch_embedded;
|
||||||
emit.first_vertex = mesh_indirect ? 0 :
|
emit.first_vertex = native_indirect ? 0 :
|
||||||
static_cast<uint32_t>(vertex_offset + static_cast<int32_t>(args.first_vertex));
|
static_cast<uint32_t>(vertex_offset + static_cast<int32_t>(args.first_vertex));
|
||||||
emit.first_instance = mesh_indirect ? 0 : instance_offset;
|
emit.first_instance = native_indirect ? 0 : instance_offset;
|
||||||
|
|
||||||
DrawIndexBufferSource index_source {};
|
DrawIndexBufferSource index_source {};
|
||||||
ExecutePreparedDraw(submit_id, buffer, draw, state, topology, emit, index_source, false);
|
ExecutePreparedDraw(submit_id, buffer, draw, state, topology, emit, index_source, false);
|
||||||
|
|||||||
@@ -386,6 +386,11 @@ struct TextureCacheTestAccess {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct RenderExecutorTestAccess {
|
struct RenderExecutorTestAccess {
|
||||||
|
static void DrawIndex(RenderExecutor &executor, CommandBuffer &command,
|
||||||
|
const DrawIndexArgs &args) {
|
||||||
|
executor.DrawIndex(0, command, args);
|
||||||
|
}
|
||||||
|
|
||||||
static void DrawAuto(RenderExecutor &executor, CommandBuffer &command,
|
static void DrawAuto(RenderExecutor &executor, CommandBuffer &command,
|
||||||
const DrawAutoArgs &args) {
|
const DrawAutoArgs &args) {
|
||||||
executor.DrawAuto(0, command, args);
|
executor.DrawAuto(0, command, args);
|
||||||
@@ -15755,6 +15760,7 @@ public:
|
|||||||
constexpr uintptr_t depth_address = 0x0000000204400000ull;
|
constexpr uintptr_t depth_address = 0x0000000204400000ull;
|
||||||
constexpr uint64_t allocation_size = 0x40000;
|
constexpr uint64_t allocation_size = 0x40000;
|
||||||
constexpr uint64_t rect_address = depth_address + 0x8000;
|
constexpr uint64_t rect_address = depth_address + 0x8000;
|
||||||
|
constexpr uint64_t index_address = rect_address + 0x1000;
|
||||||
EnsureRuntimeContext();
|
EnsureRuntimeContext();
|
||||||
RenderContext context(m_runtime_context);
|
RenderContext context(m_runtime_context);
|
||||||
auto &scheduler = context.GetCommandScheduler();
|
auto &scheduler = context.GetCommandScheduler();
|
||||||
@@ -15798,6 +15804,8 @@ public:
|
|||||||
-0.75f, 0.75f, 0, 0, 0, 1, 0, 0};
|
-0.75f, 0.75f, 0, 0, 0, 1, 0, 0};
|
||||||
std::memcpy(reinterpret_cast<void *>(rect_address), rect_vertices.data(),
|
std::memcpy(reinterpret_cast<void *>(rect_address), rect_vertices.data(),
|
||||||
sizeof(rect_vertices));
|
sizeof(rect_vertices));
|
||||||
|
constexpr std::array<uint32_t, 3> indices{0, 1, 2};
|
||||||
|
std::memcpy(reinterpret_cast<void *>(index_address), indices.data(), sizeof(indices));
|
||||||
}
|
}
|
||||||
resources.MapMemory(depth_address, allocation_size);
|
resources.MapMemory(depth_address, allocation_size);
|
||||||
if (depth_feedback) {
|
if (depth_feedback) {
|
||||||
@@ -16652,6 +16660,56 @@ public:
|
|||||||
}
|
}
|
||||||
registers.SetTargetOutputMode(0, 4);
|
registers.SetTargetOutputMode(0, 4);
|
||||||
|
|
||||||
|
// Indirect arguments also reach s8/s9. Native VS prologs must add them
|
||||||
|
// exactly once, for both indexed and automatically generated indices.
|
||||||
|
static const auto indirect_vertex = [&] {
|
||||||
|
auto code = native_vertex;
|
||||||
|
for (auto &word : code) {
|
||||||
|
if (word == EncodeVopc(0xc2, InlineU32(1), 5))
|
||||||
|
word = EncodeVopc(0xc2, InlineU32(8), 5);
|
||||||
|
else if (word == EncodeVopc(0xc2, InlineU32(2), 5))
|
||||||
|
word = EncodeVopc(0xc2, InlineU32(9), 5);
|
||||||
|
}
|
||||||
|
code.insert(code.begin(), {EncodeVop2(0x25, 5, 8, 5),
|
||||||
|
EncodeVop2(0x25, 8, 9, 8)});
|
||||||
|
const auto position = std::ranges::find(code, EncodeExp0(0x0c, 0xf));
|
||||||
|
code.insert(position, {EncodeVopc(0xc2, InlineU32(5), 8),
|
||||||
|
EncodeVop2(0x01, 3, Vgpr(1), 3),
|
||||||
|
EncodeVop2(0x01, 4, Vgpr(1), 4)});
|
||||||
|
return code;
|
||||||
|
}();
|
||||||
|
const auto indirect_vs = reinterpret_cast<uint64_t>(indirect_vertex.data());
|
||||||
|
ShaderMapUserData(indirect_vs,
|
||||||
|
{.type = Prospero::ShaderBinaryType::kGs, .user_data = &native_user_data,
|
||||||
|
.code_size_bytes = static_cast<uint32_t>(indirect_vertex.size() * sizeof(u32))});
|
||||||
|
shaders.SetEsShaderBase(indirect_vs);
|
||||||
|
shaders.SetPsShaderBase(pixel_address);
|
||||||
|
shaders.SetGsShaderResource2({.user_sgpr = 2});
|
||||||
|
shaders.SetGsUserSgpr(0, 7, HW::UserSgprType::Unknown);
|
||||||
|
shaders.SetGsUserSgpr(1, 5, HW::UserSgprType::Unknown);
|
||||||
|
user_config.SetPrimitiveType(Prospero::PrimitiveType::kTriList);
|
||||||
|
for (const bool indexed : {false, true}) {
|
||||||
|
TextureCacheTestAccess::ClearImage(cache, scheduler.Current(), sparse_color.image_id,
|
||||||
|
{vk::ImageAspectFlagBits::eColor, 0, 1, 0, 1}, {});
|
||||||
|
if (indexed) {
|
||||||
|
RenderExecutorTestAccess::DrawIndex(executor, scheduler.Current(),
|
||||||
|
{.index_count = 3, .index_addr = reinterpret_cast<const void *>(index_address),
|
||||||
|
.instance_count = 1, .index_type_and_size = 1, .base_vertex = 7, .first_instance = 5,
|
||||||
|
.offset_source = DrawOffsetSource::IndirectArgs});
|
||||||
|
} else {
|
||||||
|
RenderExecutorTestAccess::DrawAuto(executor, scheduler.Current(),
|
||||||
|
{.vertex_count = 3, .instance_count = 1, .first_vertex = 7, .first_instance = 5,
|
||||||
|
.offset_source = DrawOffsetSource::IndirectArgs});
|
||||||
|
}
|
||||||
|
const auto pixels = ReadCachedTexel(name, context, sparse_color.image_id,
|
||||||
|
{}, {extent, extent, 1});
|
||||||
|
for (size_t component = 0; component < pixels.size(); component++) {
|
||||||
|
Require("NativeIndirectDrawOffsets", indexed ? "indexed" : "auto",
|
||||||
|
pixels[component] == (component % 4 == 3 ? 0x3f800000u : 0x3e800000u),
|
||||||
|
"native vertex or instance offset was applied twice");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A fourth VS invocation reads beyond the descriptor instead of reconstructing the corner.
|
// A fourth VS invocation reads beyond the descriptor instead of reconstructing the corner.
|
||||||
const ShaderBufferResource rect_buffer{{
|
const ShaderBufferResource rect_buffer{{
|
||||||
static_cast<u32>(rect_address),
|
static_cast<u32>(rect_address),
|
||||||
|
|||||||
Reference in New Issue
Block a user