mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 10:56:58 +02:00
remove readback hacks, allows to read/write guest memory directly
This commit is contained in:
@@ -1,7 +1,3 @@
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
|
||||
#include "graphics/host_gpu/renderer/renderInternal.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common.h"
|
||||
#include "common/emulatorConfig.h"
|
||||
@@ -19,7 +15,9 @@
|
||||
#include "graphics/host_gpu/renderer/descriptorCache.h"
|
||||
#include "graphics/host_gpu/renderer/framebufferCache.h"
|
||||
#include "graphics/host_gpu/renderer/pipelineCache.h"
|
||||
#include "graphics/host_gpu/renderer/render.h"
|
||||
#include "graphics/host_gpu/renderer/renderContext.h"
|
||||
#include "graphics/host_gpu/renderer/renderInternal.h"
|
||||
#include "graphics/host_gpu/renderer/renderState.h"
|
||||
#include "graphics/host_gpu/renderer/shaderResourceBarrier.h"
|
||||
#include "graphics/host_gpu/renderer/shaderSubgroup.h"
|
||||
@@ -603,11 +601,12 @@ struct DrawEmitInfo {
|
||||
uint32_t first_vertex = 0;
|
||||
};
|
||||
|
||||
struct DrawIndexBufferBind {
|
||||
bool enabled = false;
|
||||
VulkanBuffer* buffer = nullptr;
|
||||
VkDeviceSize offset = 0;
|
||||
VkIndexType type = VK_INDEX_TYPE_UINT16;
|
||||
struct DrawIndexBufferSource {
|
||||
bool enabled = false;
|
||||
uint64_t address = 0;
|
||||
const void* host_data = nullptr;
|
||||
uint64_t size = 0;
|
||||
VkIndexType type = VK_INDEX_TYPE_UINT16;
|
||||
};
|
||||
|
||||
static uint64_t VertexBufferDescriptorSize(const ShaderVertexInputBuffer& buffer) {
|
||||
@@ -802,6 +801,32 @@ static void BindDrawVertexBuffers(uint64_t submit_id, CommandBuffer* buffer,
|
||||
}
|
||||
}
|
||||
|
||||
static void BindDrawIndexBuffer(CommandBuffer* buffer, VkCommandBuffer vk_buffer,
|
||||
const DrawIndexBufferSource& source) {
|
||||
if (!source.enabled) {
|
||||
return;
|
||||
}
|
||||
EXIT_IF(source.size == 0);
|
||||
|
||||
VulkanBuffer* index_buffer = nullptr;
|
||||
VkDeviceSize index_offset = 0;
|
||||
if (source.host_data != nullptr) {
|
||||
VkDeviceSize range = 0;
|
||||
if (!g_render_ctx->GetBufferCache()->UploadHostData(
|
||||
buffer, g_render_ctx->GetGraphicCtx(), source.host_data, source.size, 16,
|
||||
&index_buffer, &index_offset, &range)) {
|
||||
EXIT("failed to upload host index buffer\n");
|
||||
}
|
||||
} else {
|
||||
auto binding = g_render_ctx->GetBufferCache()->ObtainBuffer(
|
||||
buffer, g_render_ctx->GetGraphicCtx(), source.address, source.size);
|
||||
index_buffer = binding.first;
|
||||
index_offset = binding.second;
|
||||
}
|
||||
EXIT_IF(index_buffer == nullptr);
|
||||
vkCmdBindIndexBuffer(vk_buffer, index_buffer->buffer, index_offset, source.type);
|
||||
}
|
||||
|
||||
static void LogDrawStateIfNeeded(HW::Context* ctx, HW::UserConfig* ucfg, const DrawCallInfo& draw,
|
||||
const DrawRenderState& state, bool always_log,
|
||||
bool force_legacy_rect_log, uint32_t index_type_and_size,
|
||||
@@ -898,7 +923,7 @@ static void EmitDrawPrimitives(const HW::UserConfig* ucfg, VkCommandBuffer vk_bu
|
||||
static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx,
|
||||
HW::UserConfig* ucfg, HW::Shader* sh_ctx, const DrawCallInfo& draw,
|
||||
DrawRenderState* state, VkPrimitiveTopology topology,
|
||||
const DrawEmitInfo& emit, const DrawIndexBufferBind& index_bind,
|
||||
const DrawEmitInfo& emit, const DrawIndexBufferSource& index_source,
|
||||
bool log_pipeline_phase, bool set_bind_debug, bool set_auto_debug) {
|
||||
EXIT_IF(buffer == nullptr);
|
||||
EXIT_IF(ctx == nullptr);
|
||||
@@ -907,86 +932,93 @@ static void ExecutePreparedDraw(uint64_t submit_id, CommandBuffer* buffer, HW::C
|
||||
EXIT_IF(draw.name == nullptr);
|
||||
EXIT_IF(state == nullptr);
|
||||
|
||||
if (log_pipeline_phase) {
|
||||
LogDrawPhase(draw.name, "CreatePipeline");
|
||||
}
|
||||
auto* pipeline = g_render_ctx->GetPipelineCache()->CreateGraphicsPipeline(
|
||||
state->framebuffer, state->color_info, state->color_count, &state->depth_info,
|
||||
&state->vs_input_info, ctx, sh_ctx, &state->ps_input_info, topology, state->ps_active,
|
||||
state->vs_shader, state->ps_shader);
|
||||
for (;;) {
|
||||
const auto recording_generation = buffer->GetRecordingGeneration();
|
||||
if (log_pipeline_phase) {
|
||||
LogDrawPhase(draw.name, "CreatePipeline");
|
||||
}
|
||||
auto* pipeline = g_render_ctx->GetPipelineCache()->CreateGraphicsPipeline(
|
||||
state->framebuffer, state->color_info, state->color_count, &state->depth_info,
|
||||
&state->vs_input_info, ctx, sh_ctx, &state->ps_input_info, topology, state->ps_active,
|
||||
state->vs_shader, state->ps_shader);
|
||||
|
||||
if (set_bind_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x100u);
|
||||
}
|
||||
vkCmdBindPipeline(state->vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
|
||||
const auto dynamic_params =
|
||||
BuildGraphicsDynamicParams(*ctx, state->color_info, state->color_count, state->depth_info);
|
||||
SetDynamicParams(state->vk_buffer, dynamic_params);
|
||||
if (set_bind_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x100u);
|
||||
}
|
||||
vkCmdBindPipeline(state->vk_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline);
|
||||
const auto dynamic_params = BuildGraphicsDynamicParams(
|
||||
*ctx, state->color_info, state->color_count, state->depth_info);
|
||||
SetDynamicParams(state->vk_buffer, dynamic_params);
|
||||
|
||||
// EXIT_NOT_IMPLEMENTED(vs_input_info.buffers_num > 1);
|
||||
BindDrawVertexBuffers(submit_id, buffer, draw, state->vk_buffer, state->vs_input_info);
|
||||
// EXIT_NOT_IMPLEMENTED(vs_input_info.buffers_num > 1);
|
||||
BindDrawVertexBuffers(submit_id, buffer, draw, state->vk_buffer, state->vs_input_info);
|
||||
|
||||
LogDrawPhase(draw.name, "BindDescriptorsVS");
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x200u);
|
||||
}
|
||||
const auto vs_address_writes = BindDescriptors(
|
||||
submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout,
|
||||
state->vs_input_info.stage, VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex);
|
||||
|
||||
std::vector<ShaderAddressWriteRange> ps_address_writes;
|
||||
if (state->ps_active) {
|
||||
LogDrawPhase(draw.name, "BindDescriptorsPS");
|
||||
LogDrawPhase(draw.name, "BindDescriptorsVS");
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x300u);
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x200u);
|
||||
}
|
||||
ps_address_writes =
|
||||
BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline->pipeline_layout, state->ps_input_info.stage,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel);
|
||||
}
|
||||
const auto vs_address_writes = BindDescriptors(
|
||||
submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline->pipeline_layout,
|
||||
state->vs_input_info.stage, VK_SHADER_STAGE_VERTEX_BIT, DescriptorCache::Stage::Vertex);
|
||||
|
||||
if (index_bind.enabled) {
|
||||
EXIT_NOT_IMPLEMENTED(index_bind.buffer == nullptr);
|
||||
vkCmdBindIndexBuffer(state->vk_buffer, index_bind.buffer->buffer, index_bind.offset,
|
||||
index_bind.type);
|
||||
}
|
||||
|
||||
LogDrawPhase(draw.name, "BeginRenderPass");
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x400u);
|
||||
}
|
||||
buffer->BeginRenderPass(state->framebuffer, state->color_info, state->color_count,
|
||||
&state->depth_info);
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x500u);
|
||||
}
|
||||
|
||||
EmitDrawPrimitives(ucfg, state->vk_buffer, state->vs_input_info, draw, emit);
|
||||
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x600u);
|
||||
}
|
||||
buffer->EndRenderPass();
|
||||
VkPipelineStageFlags shader_write_stages = 0;
|
||||
const bool vs_wrote_buffers = HasShaderBufferWrites(state->vs_input_info.stage);
|
||||
const bool vs_wrote_addresses = MarkShaderAddressWrites(vs_address_writes);
|
||||
if (vs_wrote_buffers || vs_wrote_addresses) {
|
||||
shader_write_stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
||||
}
|
||||
if (state->ps_active) {
|
||||
const bool ps_wrote_buffers = HasShaderBufferWrites(state->ps_input_info.stage);
|
||||
const bool ps_wrote_addresses = MarkShaderAddressWrites(ps_address_writes);
|
||||
if (ps_wrote_buffers || ps_wrote_addresses) {
|
||||
shader_write_stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
std::vector<ShaderAddressWriteRange> ps_address_writes;
|
||||
if (state->ps_active) {
|
||||
LogDrawPhase(draw.name, "BindDescriptorsPS");
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x300u);
|
||||
}
|
||||
ps_address_writes =
|
||||
BindDescriptors(submit_id, buffer, VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
pipeline->pipeline_layout, state->ps_input_info.stage,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, DescriptorCache::Stage::Pixel);
|
||||
}
|
||||
}
|
||||
if (shader_write_stages != 0) {
|
||||
ShaderWriteBarrier(state->vk_buffer, shader_write_stages);
|
||||
}
|
||||
LogDrawPhase(draw.name, "EndRenderPass");
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x700u);
|
||||
if (buffer->GetRecordingGeneration() != recording_generation) {
|
||||
continue;
|
||||
}
|
||||
// Index data may use this command buffer's host stream. Resolve it only after the other
|
||||
// fault-capable bindings, and rebuild it whenever a fault reset changes the generation.
|
||||
BindDrawIndexBuffer(buffer, state->vk_buffer, index_source);
|
||||
if (buffer->GetRecordingGeneration() != recording_generation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
LogDrawPhase(draw.name, "BeginRenderPass");
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x400u);
|
||||
}
|
||||
buffer->BeginRenderPass(state->framebuffer, state->color_info, state->color_count,
|
||||
&state->depth_info);
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x500u);
|
||||
}
|
||||
|
||||
EmitDrawPrimitives(ucfg, state->vk_buffer, state->vs_input_info, draw, emit);
|
||||
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x600u);
|
||||
}
|
||||
buffer->EndRenderPass();
|
||||
VkPipelineStageFlags shader_write_stages = 0;
|
||||
const bool vs_wrote_buffers = HasShaderBufferWrites(state->vs_input_info.stage);
|
||||
const bool vs_wrote_addresses = MarkShaderAddressWrites(vs_address_writes);
|
||||
if (vs_wrote_buffers || vs_wrote_addresses) {
|
||||
shader_write_stages |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
||||
}
|
||||
if (state->ps_active) {
|
||||
const bool ps_wrote_buffers = HasShaderBufferWrites(state->ps_input_info.stage);
|
||||
const bool ps_wrote_addresses = MarkShaderAddressWrites(ps_address_writes);
|
||||
if (ps_wrote_buffers || ps_wrote_addresses) {
|
||||
shader_write_stages |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
}
|
||||
}
|
||||
if (shader_write_stages != 0) {
|
||||
ShaderWriteBarrier(state->vk_buffer, shader_write_stages);
|
||||
}
|
||||
LogDrawPhase(draw.name, "EndRenderPass");
|
||||
if (set_auto_debug) {
|
||||
SetDrawDebugPhase(buffer, submit_id, draw, 0x700u);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1068,7 +1100,7 @@ void RenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx
|
||||
index_type = VK_INDEX_TYPE_UINT32;
|
||||
index_size = 4 * static_cast<uint64_t>(index_count);
|
||||
break;
|
||||
// Some games use it
|
||||
// Some games use it - need vulkan extension
|
||||
case Prospero::IndexType::kIndex8:
|
||||
index_type = VK_INDEX_TYPE_UINT16;
|
||||
index_size = static_cast<uint64_t>(index_count);
|
||||
@@ -1086,6 +1118,25 @@ void RenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx
|
||||
const DrawCallInfo draw {"DrawIndex", CommandBufferDebugOp::DrawIndex,
|
||||
index_count, flags,
|
||||
instance_count, first_instance};
|
||||
std::vector<uint16_t> expanded_indices;
|
||||
if (expand_index8_to_u16) {
|
||||
EXIT_NOT_IMPLEMENTED(index_addr == nullptr);
|
||||
const auto* src = static_cast<const uint8_t*>(index_addr);
|
||||
expanded_indices.resize(index_count);
|
||||
for (uint32_t i = 0; i < index_count; i++) {
|
||||
expanded_indices[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
DrawIndexBufferSource index_source {};
|
||||
index_source.enabled = true;
|
||||
index_source.address = reinterpret_cast<uint64_t>(index_addr);
|
||||
index_source.host_data =
|
||||
expanded_indices.empty() ? nullptr : static_cast<const void*>(expanded_indices.data());
|
||||
index_source.size = expanded_indices.empty()
|
||||
? index_size
|
||||
: expanded_indices.size() * sizeof(uint16_t);
|
||||
index_source.type = index_type;
|
||||
|
||||
DrawRenderState state {};
|
||||
if (!PrepareDrawRenderState(submit_id, buffer, ctx, ucfg, sh_ctx, draw,
|
||||
@@ -1100,43 +1151,12 @@ void RenderDrawIndex(uint64_t submit_id, CommandBuffer* buffer, HW::Context* ctx
|
||||
const auto vertex_offset =
|
||||
ResolveVertexOffset(ucfg->GetIndexOffset(), state.vs_input_info) + vertex_offset_add;
|
||||
|
||||
VkDeviceSize index_offset = 0;
|
||||
VulkanBuffer* indices = nullptr;
|
||||
if (expand_index8_to_u16) {
|
||||
EXIT_NOT_IMPLEMENTED(index_addr == nullptr);
|
||||
const auto* src = static_cast<const uint8_t*>(index_addr);
|
||||
std::vector<uint16_t> expanded_indices(index_count);
|
||||
for (uint32_t i = 0; i < index_count; i++) {
|
||||
expanded_indices[i] = src[i];
|
||||
}
|
||||
VkDeviceSize range = 0;
|
||||
if (!g_render_ctx->GetBufferCache()->UploadHostData(
|
||||
buffer, g_render_ctx->GetGraphicCtx(), expanded_indices.data(),
|
||||
expanded_indices.size() * sizeof(uint16_t), 16, &indices, &index_offset, &range)) {
|
||||
EXIT("failed to upload expanded 8-bit index buffer\n");
|
||||
}
|
||||
} else {
|
||||
auto binding = g_render_ctx->GetBufferCache()->ObtainBuffer(
|
||||
buffer, g_render_ctx->GetGraphicCtx(), reinterpret_cast<uint64_t>(index_addr),
|
||||
index_size);
|
||||
indices = binding.first;
|
||||
index_offset = binding.second;
|
||||
}
|
||||
|
||||
EXIT_NOT_IMPLEMENTED(indices == nullptr);
|
||||
|
||||
DrawIndexBufferBind index_bind {};
|
||||
index_bind.enabled = true;
|
||||
index_bind.buffer = indices;
|
||||
index_bind.offset = index_offset;
|
||||
index_bind.type = index_type;
|
||||
|
||||
DrawEmitInfo emit {};
|
||||
emit.indexed = true;
|
||||
emit.vertex_offset = vertex_offset;
|
||||
|
||||
ExecutePreparedDraw(submit_id, buffer, ctx, ucfg, sh_ctx, draw, &state, topology, emit,
|
||||
index_bind, true, true, false);
|
||||
index_source, true, true, false);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||
@@ -1243,9 +1263,9 @@ void RenderDrawIndexAuto(uint64_t submit_id, CommandBuffer* buffer, HW::Context*
|
||||
emit.draw_vertex_count = draw_vertex_count;
|
||||
emit.first_vertex = static_cast<uint32_t>(vertex_offset);
|
||||
|
||||
DrawIndexBufferBind index_bind {};
|
||||
DrawIndexBufferSource index_source {};
|
||||
ExecutePreparedDraw(submit_id, buffer, ctx, ucfg, sh_ctx, draw, &state, topology, emit,
|
||||
index_bind, false, false, true);
|
||||
index_source, false, false, true);
|
||||
}
|
||||
|
||||
bool IsSameColorResolveSubresource(const RenderColorInfo& src, const RenderColorInfo& dst) {
|
||||
|
||||
Reference in New Issue
Block a user