Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ add_library(hydra-core
hw/tegra_x1/gpu/renderer/shader_decompiler/codegen/lang/msl/emitter.hpp
hw/tegra_x1/gpu/renderer/const.cpp
hw/tegra_x1/gpu/renderer/const.hpp
hw/tegra_x1/gpu/renderer/command_buffer.hpp
hw/tegra_x1/gpu/renderer/surface_compositor.hpp
hw/tegra_x1/gpu/renderer/buffer_base.hpp
hw/tegra_x1/gpu/renderer/buffer_view.hpp
Expand Down Expand Up @@ -577,6 +578,8 @@ add_library(hydra-core
hw/tegra_x1/gpu/renderer/metal/maxwell_to_mtl.cpp
hw/tegra_x1/gpu/renderer/metal/maxwell_to_mtl.hpp
hw/tegra_x1/gpu/renderer/metal/impl.cpp
hw/tegra_x1/gpu/renderer/metal/command_buffer.cpp
hw/tegra_x1/gpu/renderer/metal/command_buffer.hpp
hw/tegra_x1/gpu/renderer/metal/surface_compositor.cpp
hw/tegra_x1/gpu/renderer/metal/surface_compositor.hpp
hw/tegra_x1/gpu/renderer/metal/buffer.cpp
Expand Down
35 changes: 19 additions & 16 deletions src/core/emulation_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "core/hw/tegra_x1/cpu/mmu.hpp"
#include "core/hw/tegra_x1/cpu/thread.hpp"
#include "core/hw/tegra_x1/gpu/renderer/buffer_base.hpp"
#include "core/hw/tegra_x1/gpu/renderer/command_buffer.hpp"
#include "core/hw/tegra_x1/gpu/renderer/surface_compositor.hpp"
#include "core/hw/tegra_x1/gpu/renderer/texture_base.hpp"
#include "core/input/device_manager.hpp"
Expand Down Expand Up @@ -445,11 +446,15 @@ void EmulationContext::ProgressFrame(u32 width, u32 height,
accumulated_dt += layer->GetAccumulatedDT();
}

// Command buffer
auto command_buffer = gpu->GetRenderer().CreateCommandBuffer();

// Acquire present textures
bool acquired = os->GetDisplayDriver().AcquirePresentTextures();
bool acquired =
os->GetDisplayDriver().AcquirePresentTextures(command_buffer);

// Render pass
os->GetDisplayDriver().Present(compositor, width, height);
os->GetDisplayDriver().Present(command_buffer, compositor, width, height);

if (loading) {
if (acquired) {
Expand Down Expand Up @@ -490,9 +495,9 @@ void EmulationContext::ProgressFrame(u32 width, u32 height,
int2 size = {(i32)nintendo_logo->GetDescriptor().width,
(i32)nintendo_logo->GetDescriptor().height};
int2 dst_offset = {32, 32};
compositor->DrawTexture(nintendo_logo, IntRect2D({0, 0}, size),
IntRect2D(dst_offset, size), true,
opacity);
compositor->DrawTexture(
command_buffer, nintendo_logo, IntRect2D({0, 0}, size),
IntRect2D(dst_offset, size), true, opacity);
}

// Startup movie
Expand All @@ -510,9 +515,9 @@ void EmulationContext::ProgressFrame(u32 width, u32 height,
(i32)frame->GetDescriptor().height};
int2 dst_offset = {(i32)width - size.x() - 32,
(i32)height - size.y() - 32};
compositor->DrawTexture(frame, IntRect2D({0, 0}, size),
IntRect2D(dst_offset, size), true,
opacity);
compositor->DrawTexture(
command_buffer, frame, IntRect2D({0, 0}, size),
IntRect2D(dst_offset, size), true, opacity);
}
}
} else {
Expand All @@ -533,6 +538,9 @@ void EmulationContext::ProgressFrame(u32 width, u32 height,
}
}

compositor->Present(command_buffer);

delete command_buffer;
delete compositor;

// Signal V-Sync
Expand Down Expand Up @@ -575,12 +583,11 @@ void EmulationContext::TakeScreenshot() {
}

// Copy to a buffer
RENDERER_INSTANCE.LockMutex();
auto command_buffer = RENDERER_INSTANCE.CreateCommandBuffer();
auto buffer = RENDERER_INSTANCE.AllocateTemporaryBuffer(
static_cast<u32>(rect.size.y() * rect.size.x() * 4));
buffer->CopyFrom(texture, rect.origin, rect.size);
RENDERER_INSTANCE.EndCommandBuffer();
RENDERER_INSTANCE.UnlockMutex();
buffer->CopyFrom(command_buffer, texture, rect.origin, rect.size);
delete command_buffer;

// TODO: wait for the command buffer to finish

Expand All @@ -598,18 +605,14 @@ void EmulationContext::TakeScreenshot() {
stbi_flip_vertically_on_write(false);

// Free the buffer
RENDERER_INSTANCE.LockMutex();
RENDERER_INSTANCE.FreeTemporaryBuffer(buffer);
RENDERER_INSTANCE.UnlockMutex();
});
thread.detach();
}

void EmulationContext::CaptureGpuFrame() {
// TODO: allow multiple frames
gpu->GetRenderer().LockMutex();
gpu->GetRenderer().CaptureFrames(1);
gpu->GetRenderer().UnlockMutex();
}

void EmulationContext::TryApplyPatch(horizon::kernel::Process* process,
Expand Down
2 changes: 0 additions & 2 deletions src/core/horizon/display/binder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,7 @@ void Binder::QueueBuffer(i32 slot, const BqBufferInput& input) {

// Debug
// TODO: only do this for the main process
RENDERER_INSTANCE.LockMutex();
RENDERER_INSTANCE.NotifyDebugFrameBoundary();
RENDERER_INSTANCE.UnlockMutex();
}

i32 Binder::ConsumeBuffer(BqBufferInput& out_input) {
Expand Down
10 changes: 7 additions & 3 deletions src/core/horizon/display/driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,25 @@ namespace hydra::horizon::display {

Driver::Driver() { display_pool.Add(new Display()); }

bool Driver::AcquirePresentTextures() {
bool Driver::AcquirePresentTextures(
hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer) {
bool acquired = false;
{
std::lock_guard lock(layer_mutex);
for (u32 layer_id = 1; layer_id < layer_pool.GetCapacity() + 1;
layer_id++) {
if (!layer_pool.IsValid(layer_id))
continue;
acquired |= layer_pool.Get(layer_id)->AcquirePresentTexture();
acquired |=
layer_pool.Get(layer_id)->AcquirePresentTexture(command_buffer);
}
}

return acquired;
}

void Driver::Present(
hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer,
hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor, u32 width,
u32 height) {
std::lock_guard lock(layer_mutex);
Expand Down Expand Up @@ -67,7 +70,8 @@ void Driver::Present(

// Present
for (u32 i = 0; i < sorted_layers.size(); i++)
sorted_layers[i]->Present(compositor, dst_rect, dst_scale, i != 0);
sorted_layers[i]->Present(command_buffer, compositor, dst_rect,
dst_scale, i != 0);
}

void Driver::SignalVSync() {
Expand Down
6 changes: 4 additions & 2 deletions src/core/horizon/display/driver.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,10 @@ class Driver {
}

// Presenting
bool AcquirePresentTextures();
void Present(hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor,
bool AcquirePresentTextures(
hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer);
void Present(hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer,
hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor,
u32 width, u32 height);
void SignalVSync();

Expand Down
13 changes: 8 additions & 5 deletions src/core/horizon/display/layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

namespace hydra::horizon::display {

bool Layer::AcquirePresentTexture() {
bool Layer::AcquirePresentTexture(
hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer) {
// Get the buffer to present
auto& binder = OS_INSTANCE.GetDisplayDriver().GetBinder(binder_id);

Expand All @@ -19,8 +20,8 @@ bool Layer::AcquirePresentTexture() {
const auto& buffer = binder.GetBuffer(slot);

// Texture
present_texture =
GPU_INSTANCE.GetTexture(process->GetMmu(), buffer.nv_buffer);
present_texture = GPU_INSTANCE.GetTexture(command_buffer, process->GetMmu(),
buffer.nv_buffer);

// Rect
src_rect = {};
Expand Down Expand Up @@ -58,7 +59,8 @@ bool Layer::AcquirePresentTexture() {
return true;
}

void Layer::Present(hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor,
void Layer::Present(hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer,
hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor,
FloatRect2D dst_rect, f32 dst_scale, bool transparent) {
if (!present_texture)
return;
Expand All @@ -68,7 +70,8 @@ void Layer::Present(hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor,
dst_rect.size = float2(size) * dst_scale;

// Draw
compositor->DrawTexture(present_texture, src_rect, dst_rect, transparent);
compositor->DrawTexture(command_buffer, present_texture, src_rect, dst_rect,
transparent);
}

AccumulatedTime Layer::GetAccumulatedDT() {
Expand Down
7 changes: 5 additions & 2 deletions src/core/horizon/display/layer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

namespace hydra::hw::tegra_x1::gpu::renderer {
class TextureBase;
class ICommandBuffer;
class ISurfaceCompositor;
} // namespace hydra::hw::tegra_x1::gpu::renderer

Expand All @@ -21,8 +22,10 @@ class Layer {
void Open() {}
void Close() {}

bool AcquirePresentTexture();
void Present(hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor,
bool AcquirePresentTexture(
hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer);
void Present(hw::tegra_x1::gpu::renderer::ICommandBuffer* command_buffer,
hw::tegra_x1::gpu::renderer::ISurfaceCompositor* compositor,
FloatRect2D dst_rect, f32 dst_scale, bool transparent);

// Time
Expand Down
26 changes: 16 additions & 10 deletions src/core/horizon/services/nvdrv/ioctl/nvhost_gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ NvResult NvHostGpu::SubmitGpfifo(

GPU_INSTANCE.GetPfifo().SubmitEntries(
*process->GetGMmu(),
std::vector<hw::tegra_x1::gpu::GpfifoEntry>(entries,
entries + num_entries),
std::span<const hw::tegra_x1::gpu::GpfifoEntry>(entries, num_entries),
inout_flags_and_detailed_error);

// HACK
Expand All @@ -59,21 +58,25 @@ NvResult NvHostGpu::SubmitGpfifo(
}

NvResult NvHostGpu::AllocObjCtx(u32 class_num, u32 flags, u64* out_obj_id) {
LOG_FUNC_WITH_ARGS_STUBBED(Services, "class number: {}, flags: {:#x}", class_num, flags);
LOG_FUNC_WITH_ARGS_STUBBED(Services, "class number: {}, flags: {:#x}",
class_num, flags);

// HACK
*out_obj_id = 0;
return NvResult::Success;
}

NvResult NvHostGpu::ZCullBind(gpu_vaddr_t addr, u32 mode, [[maybe_unused]] u32 reserved) {
LOG_FUNC_WITH_ARGS_STUBBED(Services, "address: {:#x}, mode: {}", addr, mode);
NvResult NvHostGpu::ZCullBind(gpu_vaddr_t addr, u32 mode,
[[maybe_unused]] u32 reserved) {
LOG_FUNC_WITH_ARGS_STUBBED(Services, "address: {:#x}, mode: {}", addr,
mode);
return NvResult::Success;
}

NvResult NvHostGpu::SetErrorNotifier(u64 offset, u64 size, u32 mem,
[[maybe_unused]] u32 reserved) {
LOG_FUNC_WITH_ARGS_STUBBED(Services, "offset: {:#x}, size: {:#x}, memory: {}", offset, size, mem);
LOG_FUNC_WITH_ARGS_STUBBED(
Services, "offset: {:#x}, size: {:#x}, memory: {}", offset, size, mem);
return NvResult::Success;
}

Expand All @@ -89,10 +92,13 @@ NvResult NvHostGpu::GetErrorNotification(u64* out_timestamp, u32* out_info32,
return NvResult::Success;
}

NvResult NvHostGpu::AllocGpfifoEX(u32 num_entries, u32 num_jobs, u32 flags,
hw::tegra_x1::gpu::Fence* out_fence,
[[maybe_unused]] std::array<u32, 3> reserved) {
LOG_FUNC_WITH_ARGS_STUBBED(Services, "number of entries: {}, num_jobs: {}, flags: {:#x}", num_entries, num_jobs, flags);
NvResult
NvHostGpu::AllocGpfifoEX(u32 num_entries, u32 num_jobs, u32 flags,
hw::tegra_x1::gpu::Fence* out_fence,
[[maybe_unused]] std::array<u32, 3> reserved) {
LOG_FUNC_WITH_ARGS_STUBBED(
Services, "number of entries: {}, num_jobs: {}, flags: {:#x}",
num_entries, num_jobs, flags);

// HACK
*out_fence = {};
Expand Down
16 changes: 8 additions & 8 deletions src/core/hw/tegra_x1/gpu/engines/2d.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,13 @@ DEFINE_METHOD_TABLE(TwoD, 0x237, 1, Copy, u32)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"

void TwoD::Copy(GMmu& gmmu, const u32 index,
const u32 pixels_from_memory_src_y0_int) {
void TwoD::Copy(const u32 index, const u32 pixels_from_memory_src_y0_int) {
auto& pixels = regs.pixels_from_memory;
pixels.src_y0.integer = pixels_from_memory_src_y0_int;

// TODO: can these also not be textures?
auto src = GetTexture(gmmu, regs.src, renderer::TextureUsage::Read);
auto dst = GetTexture(gmmu, regs.dst, renderer::TextureUsage::Write);
auto src = GetTexture(regs.src, renderer::TextureUsage::Read);
auto dst = GetTexture(regs.dst, renderer::TextureUsage::Write);

const auto dudx = static_cast<f64>(pixels.dudx);
const auto dvdy = static_cast<f64>(pixels.dvdy);
Expand All @@ -28,7 +27,7 @@ void TwoD::Copy(GMmu& gmmu, const u32 index,
const auto src_width = static_cast<u32>(pixels.dst_width * dudx);
const auto src_height = static_cast<u32>(pixels.dst_height * dvdy);

dst->BlitFrom(src,
dst->BlitFrom(tls_crnt_command_buffer, src,
{static_cast<f32>(src_x0), static_cast<f32>(src_y0),
static_cast<f32>(regs.src.layer)},
{src_width, src_height, 1},
Expand All @@ -40,10 +39,10 @@ void TwoD::Copy(GMmu& gmmu, const u32 index,

#pragma GCC diagnostic pop

renderer::TextureBase* TwoD::GetTexture(GMmu& gmmu, const Texture2DInfo& info,
renderer::TextureBase* TwoD::GetTexture(const Texture2DInfo& info,
renderer::TextureUsage usage) {
const renderer::TextureDescriptor descriptor(
gmmu.UnmapAddr(info.addr), renderer::TextureType::_2D,
tls_crnt_gmmu->UnmapAddr(info.addr), renderer::TextureType::_2D,
renderer::to_texture_format(info.format),
NvKind::Pitch, // TODO: correct?
u32(info.width), u32(info.height), 1,
Expand All @@ -53,7 +52,8 @@ renderer::TextureBase* TwoD::GetTexture(GMmu& gmmu, const Texture2DInfo& info,
renderer::to_texture_format(info.format), info.width) // HACK
);

return RENDERER_INSTANCE.GetTextureCache().Find(descriptor, usage);
return RENDERER_INSTANCE.GetTextureCache().Find(tls_crnt_command_buffer,
descriptor, usage);
}

} // namespace hydra::hw::tegra_x1::gpu::engines
8 changes: 3 additions & 5 deletions src/core/hw/tegra_x1/gpu/engines/2d.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,14 @@ struct Regs2D {

class TwoD : public EngineWithRegsBase<Regs2D> {
public:
void Method(GMmu& gmmu, u32 method, u32 arg) override;
void Method(u32 method, u32 arg) override;

private:
// Commands
void Copy(GMmu& gmmu, const u32 index,
const u32 pixels_from_memory_src_y0_int);
void Copy(const u32 index, const u32 pixels_from_memory_src_y0_int);

// Helpers
static renderer::TextureBase* GetTexture(GMmu& gmmu,
const Texture2DInfo& info,
static renderer::TextureBase* GetTexture(const Texture2DInfo& info,
renderer::TextureUsage usage);
};

Expand Down
Loading