early-access version 2097
This commit is contained in:
parent
7b4c6781c9
commit
9e450f7d41
@ -1,7 +1,7 @@
|
|||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 2096.
|
This is the source code for early-access 2097.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
@ -48,8 +48,9 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3
|
|||||||
addr, offset, width, height, stride, format);
|
addr, offset, width, height, stride, format);
|
||||||
|
|
||||||
const auto pixel_format = static_cast<Tegra::FramebufferConfig::PixelFormat>(format);
|
const auto pixel_format = static_cast<Tegra::FramebufferConfig::PixelFormat>(format);
|
||||||
const Tegra::FramebufferConfig framebuffer{addr, offset, width, height,
|
const auto transform_flags = static_cast<Tegra::FramebufferConfig::TransformFlags>(transform);
|
||||||
stride, pixel_format, transform, crop_rect};
|
const Tegra::FramebufferConfig framebuffer{addr, offset, width, height,
|
||||||
|
stride, pixel_format, transform_flags, crop_rect};
|
||||||
|
|
||||||
system.GetPerfStats().EndSystemFrame();
|
system.GetPerfStats().EndSystemFrame();
|
||||||
system.GPU().SwapBuffers(&framebuffer);
|
system.GPU().SwapBuffers(&framebuffer);
|
||||||
|
@ -111,7 +111,6 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
|
|||||||
event.event->GetWritableEvent().Signal();
|
event.event->GetWritableEvent().Signal();
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
auto lock = gpu.LockSync();
|
|
||||||
const u32 current_syncpoint_value = event.fence.value;
|
const u32 current_syncpoint_value = event.fence.value;
|
||||||
const s32 diff = current_syncpoint_value - params.threshold;
|
const s32 diff = current_syncpoint_value - params.threshold;
|
||||||
if (diff >= 0) {
|
if (diff >= 0) {
|
||||||
@ -132,23 +131,24 @@ NvResult nvhost_ctrl::IocCtrlEventWait(const std::vector<u8>& input, std::vector
|
|||||||
}
|
}
|
||||||
|
|
||||||
EventState status = events_interface.status[event_id];
|
EventState status = events_interface.status[event_id];
|
||||||
if (event_id < MaxNvEvents || status == EventState::Free || status == EventState::Registered) {
|
const bool bad_parameter = status != EventState::Free && status != EventState::Registered;
|
||||||
events_interface.SetEventStatus(event_id, EventState::Waiting);
|
if (bad_parameter) {
|
||||||
events_interface.assigned_syncpt[event_id] = params.syncpt_id;
|
|
||||||
events_interface.assigned_value[event_id] = target_value;
|
|
||||||
if (is_async) {
|
|
||||||
params.value = params.syncpt_id << 4;
|
|
||||||
} else {
|
|
||||||
params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
|
|
||||||
}
|
|
||||||
params.value |= event_id;
|
|
||||||
event.event->GetWritableEvent().Clear();
|
|
||||||
gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
|
|
||||||
std::memcpy(output.data(), ¶ms, sizeof(params));
|
std::memcpy(output.data(), ¶ms, sizeof(params));
|
||||||
return NvResult::Timeout;
|
return NvResult::BadParameter;
|
||||||
}
|
}
|
||||||
|
events_interface.SetEventStatus(event_id, EventState::Waiting);
|
||||||
|
events_interface.assigned_syncpt[event_id] = params.syncpt_id;
|
||||||
|
events_interface.assigned_value[event_id] = target_value;
|
||||||
|
if (is_async) {
|
||||||
|
params.value = params.syncpt_id << 4;
|
||||||
|
} else {
|
||||||
|
params.value = ((params.syncpt_id & 0xfff) << 16) | 0x10000000;
|
||||||
|
}
|
||||||
|
params.value |= event_id;
|
||||||
|
event.event->GetWritableEvent().Clear();
|
||||||
|
gpu.RegisterSyncptInterrupt(params.syncpt_id, target_value);
|
||||||
std::memcpy(output.data(), ¶ms, sizeof(params));
|
std::memcpy(output.data(), ¶ms, sizeof(params));
|
||||||
return NvResult::BadParameter;
|
return NvResult::Timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) {
|
NvResult nvhost_ctrl::IocCtrlEventRegister(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
|
@ -13,6 +13,14 @@
|
|||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
||||||
namespace Service::Nvidia::Devices {
|
namespace Service::Nvidia::Devices {
|
||||||
|
namespace {
|
||||||
|
Tegra::CommandHeader BuildFenceAction(Tegra::GPU::FenceOperation op, u32 syncpoint_id) {
|
||||||
|
Tegra::GPU::FenceAction result{};
|
||||||
|
result.op.Assign(op);
|
||||||
|
result.syncpoint_id.Assign(syncpoint_id);
|
||||||
|
return {result.raw};
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
nvhost_gpu::nvhost_gpu(Core::System& system_, std::shared_ptr<nvmap> nvmap_dev_,
|
||||||
SyncpointManager& syncpoint_manager_)
|
SyncpointManager& syncpoint_manager_)
|
||||||
@ -187,7 +195,7 @@ static std::vector<Tegra::CommandHeader> BuildWaitCommandList(Fence fence) {
|
|||||||
{fence.value},
|
{fence.value},
|
||||||
Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1,
|
Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1,
|
||||||
Tegra::SubmissionMode::Increasing),
|
Tegra::SubmissionMode::Increasing),
|
||||||
Tegra::GPU::FenceAction::Build(Tegra::GPU::FenceOperation::Acquire, fence.id),
|
BuildFenceAction(Tegra::GPU::FenceOperation::Acquire, fence.id),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,8 +208,7 @@ static std::vector<Tegra::CommandHeader> BuildIncrementCommandList(Fence fence,
|
|||||||
for (u32 count = 0; count < add_increment; ++count) {
|
for (u32 count = 0; count < add_increment; ++count) {
|
||||||
result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1,
|
result.emplace_back(Tegra::BuildCommandHeader(Tegra::BufferMethods::FenceAction, 1,
|
||||||
Tegra::SubmissionMode::Increasing));
|
Tegra::SubmissionMode::Increasing));
|
||||||
result.emplace_back(
|
result.emplace_back(BuildFenceAction(Tegra::GPU::FenceOperation::Increment, fence.id));
|
||||||
Tegra::GPU::FenceAction::Build(Tegra::GPU::FenceOperation::Increment, fence.id));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -13,28 +13,20 @@
|
|||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
#include "core/hardware_properties.h"
|
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
|
||||||
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
|
#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h"
|
||||||
#include "core/hle/service/nvdrv/nvdrv.h"
|
#include "core/hle/service/nvdrv/nvdrv.h"
|
||||||
#include "core/hle/service/nvflinger/buffer_queue.h"
|
#include "core/hle/service/nvflinger/buffer_queue.h"
|
||||||
#include "core/hle/service/nvflinger/nvflinger.h"
|
#include "core/hle/service/nvflinger/nvflinger.h"
|
||||||
#include "core/hle/service/vi/display/vi_display.h"
|
#include "core/hle/service/vi/display/vi_display.h"
|
||||||
#include "core/hle/service/vi/layer/vi_layer.h"
|
#include "core/hle/service/vi/layer/vi_layer.h"
|
||||||
#include "core/perf_stats.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/renderer_base.h"
|
|
||||||
|
|
||||||
namespace Service::NVFlinger {
|
namespace Service::NVFlinger {
|
||||||
|
|
||||||
constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
|
constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
|
||||||
|
|
||||||
void NVFlinger::VSyncThread(NVFlinger& nv_flinger) {
|
void NVFlinger::SplitVSync(std::stop_token stop_token) {
|
||||||
nv_flinger.SplitVSync();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NVFlinger::SplitVSync() {
|
|
||||||
system.RegisterHostThread();
|
system.RegisterHostThread();
|
||||||
std::string name = "yuzu:VSyncThread";
|
std::string name = "yuzu:VSyncThread";
|
||||||
MicroProfileOnThreadCreate(name.c_str());
|
MicroProfileOnThreadCreate(name.c_str());
|
||||||
@ -45,7 +37,7 @@ void NVFlinger::SplitVSync() {
|
|||||||
Common::SetCurrentThreadName(name.c_str());
|
Common::SetCurrentThreadName(name.c_str());
|
||||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
||||||
s64 delay = 0;
|
s64 delay = 0;
|
||||||
while (is_running) {
|
while (!stop_token.stop_requested()) {
|
||||||
guard->lock();
|
guard->lock();
|
||||||
const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
|
const s64 time_start = system.CoreTiming().GetGlobalTimeNs().count();
|
||||||
Compose();
|
Compose();
|
||||||
@ -55,7 +47,7 @@ void NVFlinger::SplitVSync() {
|
|||||||
const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
|
const s64 next_time = std::max<s64>(0, ticks - time_passed - delay);
|
||||||
guard->unlock();
|
guard->unlock();
|
||||||
if (next_time > 0) {
|
if (next_time > 0) {
|
||||||
wait_event->WaitFor(std::chrono::nanoseconds{next_time});
|
std::this_thread::sleep_for(std::chrono::nanoseconds{next_time});
|
||||||
}
|
}
|
||||||
delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
|
delay = (system.CoreTiming().GetGlobalTimeNs().count() - time_end) - next_time;
|
||||||
}
|
}
|
||||||
@ -84,9 +76,7 @@ NVFlinger::NVFlinger(Core::System& system_)
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (system.IsMulticore()) {
|
if (system.IsMulticore()) {
|
||||||
is_running = true;
|
vsync_thread = std::jthread([this](std::stop_token token) { SplitVSync(token); });
|
||||||
wait_event = std::make_unique<Common::Event>();
|
|
||||||
vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this));
|
|
||||||
} else {
|
} else {
|
||||||
system.CoreTiming().ScheduleEvent(frame_ns, composition_event);
|
system.CoreTiming().ScheduleEvent(frame_ns, composition_event);
|
||||||
}
|
}
|
||||||
@ -96,14 +86,7 @@ NVFlinger::~NVFlinger() {
|
|||||||
for (auto& buffer_queue : buffer_queues) {
|
for (auto& buffer_queue : buffer_queues) {
|
||||||
buffer_queue->Disconnect();
|
buffer_queue->Disconnect();
|
||||||
}
|
}
|
||||||
|
if (!system.IsMulticore()) {
|
||||||
if (system.IsMulticore()) {
|
|
||||||
is_running = false;
|
|
||||||
wait_event->Set();
|
|
||||||
vsync_thread->join();
|
|
||||||
vsync_thread.reset();
|
|
||||||
wait_event.reset();
|
|
||||||
} else {
|
|
||||||
system.CoreTiming().UnscheduleEvent(composition_event, 0);
|
system.CoreTiming().UnscheduleEvent(composition_event, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -109,9 +106,7 @@ private:
|
|||||||
/// Creates a layer with the specified layer ID in the desired display.
|
/// Creates a layer with the specified layer ID in the desired display.
|
||||||
void CreateLayerAtId(VI::Display& display, u64 layer_id);
|
void CreateLayerAtId(VI::Display& display, u64 layer_id);
|
||||||
|
|
||||||
static void VSyncThread(NVFlinger& nv_flinger);
|
void SplitVSync(std::stop_token stop_token);
|
||||||
|
|
||||||
void SplitVSync();
|
|
||||||
|
|
||||||
std::shared_ptr<Nvidia::Module> nvdrv;
|
std::shared_ptr<Nvidia::Module> nvdrv;
|
||||||
|
|
||||||
@ -133,9 +128,7 @@ private:
|
|||||||
|
|
||||||
Core::System& system;
|
Core::System& system;
|
||||||
|
|
||||||
std::unique_ptr<std::thread> vsync_thread;
|
std::jthread vsync_thread;
|
||||||
std::unique_ptr<Common::Event> wait_event;
|
|
||||||
std::atomic<bool> is_running{};
|
|
||||||
|
|
||||||
KernelHelpers::ServiceContext service_context;
|
KernelHelpers::ServiceContext service_context;
|
||||||
};
|
};
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "command_classes/vic.h"
|
#include "command_classes/vic.h"
|
||||||
#include "video_core/cdma_pusher.h"
|
#include "video_core/cdma_pusher.h"
|
||||||
#include "video_core/command_classes/nvdec_common.h"
|
#include "video_core/command_classes/nvdec_common.h"
|
||||||
|
#include "video_core/command_classes/sync_manager.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/gpu.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
@ -9,13 +9,13 @@
|
|||||||
|
|
||||||
#include "common/bit_field.h"
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "video_core/command_classes/sync_manager.h"
|
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
||||||
class GPU;
|
class GPU;
|
||||||
class Host1x;
|
class Host1x;
|
||||||
class Nvdec;
|
class Nvdec;
|
||||||
|
class SyncptIncrManager;
|
||||||
class Vic;
|
class Vic;
|
||||||
|
|
||||||
enum class ChSubmissionMode : u32 {
|
enum class ChSubmissionMode : u32 {
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <bitset>
|
#include <bitset>
|
||||||
|
#include <cmath>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
namespace Tegra {
|
#include "common/common_types.h"
|
||||||
|
#include "common/math_util.h"
|
||||||
|
|
||||||
|
namespace Tegra {
|
||||||
/**
|
/**
|
||||||
* Struct describing framebuffer configuration
|
* Struct describing framebuffer configuration
|
||||||
*/
|
*/
|
||||||
@ -16,6 +18,21 @@ struct FramebufferConfig {
|
|||||||
B8G8R8A8_UNORM = 5,
|
B8G8R8A8_UNORM = 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class TransformFlags : u32 {
|
||||||
|
/// No transform flags are set
|
||||||
|
Unset = 0x00,
|
||||||
|
/// Flip source image horizontally (around the vertical axis)
|
||||||
|
FlipH = 0x01,
|
||||||
|
/// Flip source image vertically (around the horizontal axis)
|
||||||
|
FlipV = 0x02,
|
||||||
|
/// Rotate source image 90 degrees clockwise
|
||||||
|
Rotate90 = 0x04,
|
||||||
|
/// Rotate source image 180 degrees
|
||||||
|
Rotate180 = 0x03,
|
||||||
|
/// Rotate source image 270 degrees clockwise
|
||||||
|
Rotate270 = 0x07,
|
||||||
|
};
|
||||||
|
|
||||||
VAddr address{};
|
VAddr address{};
|
||||||
u32 offset{};
|
u32 offset{};
|
||||||
u32 width{};
|
u32 width{};
|
||||||
@ -23,7 +40,6 @@ struct FramebufferConfig {
|
|||||||
u32 stride{};
|
u32 stride{};
|
||||||
PixelFormat pixel_format{};
|
PixelFormat pixel_format{};
|
||||||
|
|
||||||
using TransformFlags = Service::NVFlinger::BufferQueue::BufferTransformFlags;
|
|
||||||
TransformFlags transform_flags{};
|
TransformFlags transform_flags{};
|
||||||
Common::Rectangle<int> crop_rect;
|
Common::Rectangle<int> crop_rect;
|
||||||
};
|
};
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -3,29 +3,12 @@
|
|||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <atomic>
|
|
||||||
#include <condition_variable>
|
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
|
||||||
|
#include "common/bit_field.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/service/nvdrv/nvdata.h"
|
|
||||||
#include "core/hle/service/nvflinger/buffer_queue.h"
|
|
||||||
#include "video_core/cdma_pusher.h"
|
#include "video_core/cdma_pusher.h"
|
||||||
#include "video_core/dma_pusher.h"
|
|
||||||
#include "video_core/framebuffer_config.h"
|
#include "video_core/framebuffer_config.h"
|
||||||
#include "video_core/gpu_thread.h"
|
|
||||||
|
|
||||||
using CacheAddr = std::uintptr_t;
|
|
||||||
[[nodiscard]] inline CacheAddr ToCacheAddr(const void* host_ptr) {
|
|
||||||
return reinterpret_cast<CacheAddr>(host_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] inline u8* FromCacheAddr(CacheAddr cache_addr) {
|
|
||||||
return reinterpret_cast<u8*>(cache_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace Frontend {
|
namespace Frontend {
|
||||||
@ -40,6 +23,9 @@ class ShaderNotify;
|
|||||||
} // namespace VideoCore
|
} // namespace VideoCore
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
class DmaPusher;
|
||||||
|
class CDmaPusher;
|
||||||
|
struct CommandList;
|
||||||
|
|
||||||
enum class RenderTargetFormat : u32 {
|
enum class RenderTargetFormat : u32 {
|
||||||
NONE = 0x0,
|
NONE = 0x0,
|
||||||
@ -138,7 +124,18 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit GPU(Core::System& system_, bool is_async_, bool use_nvdec_);
|
enum class FenceOperation : u32 {
|
||||||
|
Acquire = 0,
|
||||||
|
Increment = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
union FenceAction {
|
||||||
|
u32 raw;
|
||||||
|
BitField<0, 1, FenceOperation> op;
|
||||||
|
BitField<8, 24, u32> syncpoint_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit GPU(Core::System& system, bool is_async, bool use_nvdec);
|
||||||
~GPU();
|
~GPU();
|
||||||
|
|
||||||
/// Binds a renderer to the GPU.
|
/// Binds a renderer to the GPU.
|
||||||
@ -162,9 +159,7 @@ public:
|
|||||||
[[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size);
|
[[nodiscard]] u64 RequestFlush(VAddr addr, std::size_t size);
|
||||||
|
|
||||||
/// Obtains current flush request fence id.
|
/// Obtains current flush request fence id.
|
||||||
[[nodiscard]] u64 CurrentFlushRequestFence() const {
|
[[nodiscard]] u64 CurrentFlushRequestFence() const;
|
||||||
return current_flush_fence.load(std::memory_order_relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tick pending requests within the GPU.
|
/// Tick pending requests within the GPU.
|
||||||
void TickWork();
|
void TickWork();
|
||||||
@ -200,24 +195,16 @@ public:
|
|||||||
[[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const;
|
[[nodiscard]] const Tegra::CDmaPusher& CDmaPusher() const;
|
||||||
|
|
||||||
/// Returns a reference to the underlying renderer.
|
/// Returns a reference to the underlying renderer.
|
||||||
[[nodiscard]] VideoCore::RendererBase& Renderer() {
|
[[nodiscard]] VideoCore::RendererBase& Renderer();
|
||||||
return *renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a const reference to the underlying renderer.
|
/// Returns a const reference to the underlying renderer.
|
||||||
[[nodiscard]] const VideoCore::RendererBase& Renderer() const {
|
[[nodiscard]] const VideoCore::RendererBase& Renderer() const;
|
||||||
return *renderer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a reference to the shader notifier.
|
/// Returns a reference to the shader notifier.
|
||||||
[[nodiscard]] VideoCore::ShaderNotify& ShaderNotify() {
|
[[nodiscard]] VideoCore::ShaderNotify& ShaderNotify();
|
||||||
return *shader_notify;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a const reference to the shader notifier.
|
/// Returns a const reference to the shader notifier.
|
||||||
[[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const {
|
[[nodiscard]] const VideoCore::ShaderNotify& ShaderNotify() const;
|
||||||
return *shader_notify;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame.
|
/// Allows the CPU/NvFlinger to wait on the GPU before presenting a frame.
|
||||||
void WaitFence(u32 syncpoint_id, u32 value);
|
void WaitFence(u32 syncpoint_id, u32 value);
|
||||||
@ -232,80 +219,12 @@ public:
|
|||||||
|
|
||||||
[[nodiscard]] u64 GetTicks() const;
|
[[nodiscard]] u64 GetTicks() const;
|
||||||
|
|
||||||
[[nodiscard]] std::unique_lock<std::mutex> LockSync() {
|
[[nodiscard]] bool IsAsync() const;
|
||||||
return std::unique_lock{sync_mutex};
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool IsAsync() const {
|
[[nodiscard]] bool UseNvdec() const;
|
||||||
return is_async;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] bool UseNvdec() const {
|
|
||||||
return use_nvdec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void RendererFrameEndNotify();
|
void RendererFrameEndNotify();
|
||||||
|
|
||||||
enum class FenceOperation : u32 {
|
|
||||||
Acquire = 0,
|
|
||||||
Increment = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
union FenceAction {
|
|
||||||
u32 raw;
|
|
||||||
BitField<0, 1, FenceOperation> op;
|
|
||||||
BitField<8, 24, u32> syncpoint_id;
|
|
||||||
|
|
||||||
[[nodiscard]] static CommandHeader Build(FenceOperation op, u32 syncpoint_id) {
|
|
||||||
FenceAction result{};
|
|
||||||
result.op.Assign(op);
|
|
||||||
result.syncpoint_id.Assign(syncpoint_id);
|
|
||||||
return {result.raw};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Regs {
|
|
||||||
static constexpr size_t NUM_REGS = 0x40;
|
|
||||||
|
|
||||||
union {
|
|
||||||
struct {
|
|
||||||
INSERT_PADDING_WORDS_NOINIT(0x4);
|
|
||||||
struct {
|
|
||||||
u32 address_high;
|
|
||||||
u32 address_low;
|
|
||||||
|
|
||||||
[[nodiscard]] GPUVAddr SemaphoreAddress() const {
|
|
||||||
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
|
|
||||||
address_low);
|
|
||||||
}
|
|
||||||
} semaphore_address;
|
|
||||||
|
|
||||||
u32 semaphore_sequence;
|
|
||||||
u32 semaphore_trigger;
|
|
||||||
INSERT_PADDING_WORDS_NOINIT(0xC);
|
|
||||||
|
|
||||||
// The pusher and the puller share the reference counter, the pusher only has read
|
|
||||||
// access
|
|
||||||
u32 reference_count;
|
|
||||||
INSERT_PADDING_WORDS_NOINIT(0x5);
|
|
||||||
|
|
||||||
u32 semaphore_acquire;
|
|
||||||
u32 semaphore_release;
|
|
||||||
u32 fence_value;
|
|
||||||
FenceAction fence_action;
|
|
||||||
INSERT_PADDING_WORDS_NOINIT(0xE2);
|
|
||||||
|
|
||||||
// Puller state
|
|
||||||
u32 acquire_mode;
|
|
||||||
u32 acquire_source;
|
|
||||||
u32 acquire_active;
|
|
||||||
u32 acquire_timeout;
|
|
||||||
u32 acquire_value;
|
|
||||||
};
|
|
||||||
std::array<u32, NUM_REGS> reg_array;
|
|
||||||
};
|
|
||||||
} regs{};
|
|
||||||
|
|
||||||
/// Performs any additional setup necessary in order to begin GPU emulation.
|
/// Performs any additional setup necessary in order to begin GPU emulation.
|
||||||
/// This can be used to launch any necessary threads and register any necessary
|
/// This can be used to launch any necessary threads and register any necessary
|
||||||
/// core timing events.
|
/// core timing events.
|
||||||
@ -338,104 +257,9 @@ public:
|
|||||||
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
|
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
|
||||||
void FlushAndInvalidateRegion(VAddr addr, u64 size);
|
void FlushAndInvalidateRegion(VAddr addr, u64 size);
|
||||||
|
|
||||||
protected:
|
|
||||||
void TriggerCpuInterrupt(u32 syncpoint_id, u32 value) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ProcessBindMethod(const MethodCall& method_call);
|
struct Impl;
|
||||||
void ProcessFenceActionMethod();
|
std::unique_ptr<Impl> impl;
|
||||||
void ProcessWaitForInterruptMethod();
|
|
||||||
void ProcessSemaphoreTriggerMethod();
|
|
||||||
void ProcessSemaphoreRelease();
|
|
||||||
void ProcessSemaphoreAcquire();
|
|
||||||
|
|
||||||
/// Calls a GPU puller method.
|
|
||||||
void CallPullerMethod(const MethodCall& method_call);
|
|
||||||
|
|
||||||
/// Calls a GPU engine method.
|
|
||||||
void CallEngineMethod(const MethodCall& method_call);
|
|
||||||
|
|
||||||
/// Calls a GPU engine multivalue method.
|
|
||||||
void CallEngineMultiMethod(u32 method, u32 subchannel, const u32* base_start, u32 amount,
|
|
||||||
u32 methods_pending);
|
|
||||||
|
|
||||||
/// Determines where the method should be executed.
|
|
||||||
[[nodiscard]] bool ExecuteMethodOnEngine(u32 method);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Core::System& system;
|
|
||||||
std::unique_ptr<Tegra::MemoryManager> memory_manager;
|
|
||||||
std::unique_ptr<Tegra::DmaPusher> dma_pusher;
|
|
||||||
std::unique_ptr<Tegra::CDmaPusher> cdma_pusher;
|
|
||||||
std::unique_ptr<VideoCore::RendererBase> renderer;
|
|
||||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
|
||||||
const bool use_nvdec;
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// Mapping of command subchannels to their bound engine ids
|
|
||||||
std::array<EngineID, 8> bound_engines = {};
|
|
||||||
/// 3D engine
|
|
||||||
std::unique_ptr<Engines::Maxwell3D> maxwell_3d;
|
|
||||||
/// 2D engine
|
|
||||||
std::unique_ptr<Engines::Fermi2D> fermi_2d;
|
|
||||||
/// Compute engine
|
|
||||||
std::unique_ptr<Engines::KeplerCompute> kepler_compute;
|
|
||||||
/// DMA engine
|
|
||||||
std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
|
|
||||||
/// Inline memory engine
|
|
||||||
std::unique_ptr<Engines::KeplerMemory> kepler_memory;
|
|
||||||
/// Shader build notifier
|
|
||||||
std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
|
|
||||||
/// When true, we are about to shut down emulation session, so terminate outstanding tasks
|
|
||||||
std::atomic_bool shutting_down{};
|
|
||||||
|
|
||||||
std::array<std::atomic<u32>, Service::Nvidia::MaxSyncPoints> syncpoints{};
|
|
||||||
|
|
||||||
std::array<std::list<u32>, Service::Nvidia::MaxSyncPoints> syncpt_interrupts;
|
|
||||||
|
|
||||||
std::mutex sync_mutex;
|
|
||||||
std::mutex device_mutex;
|
|
||||||
|
|
||||||
std::condition_variable sync_cv;
|
|
||||||
|
|
||||||
struct FlushRequest {
|
|
||||||
explicit FlushRequest(u64 fence_, VAddr addr_, std::size_t size_)
|
|
||||||
: fence{fence_}, addr{addr_}, size{size_} {}
|
|
||||||
u64 fence;
|
|
||||||
VAddr addr;
|
|
||||||
std::size_t size;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::list<FlushRequest> flush_requests;
|
|
||||||
std::atomic<u64> current_flush_fence{};
|
|
||||||
u64 last_flush_fence{};
|
|
||||||
std::mutex flush_request_mutex;
|
|
||||||
|
|
||||||
const bool is_async;
|
|
||||||
|
|
||||||
VideoCommon::GPUThread::ThreadManager gpu_thread;
|
|
||||||
std::unique_ptr<Core::Frontend::GraphicsContext> cpu_context;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ASSERT_REG_POSITION(field_name, position) \
|
|
||||||
static_assert(offsetof(GPU::Regs, field_name) == position * 4, \
|
|
||||||
"Field " #field_name " has invalid position")
|
|
||||||
|
|
||||||
ASSERT_REG_POSITION(semaphore_address, 0x4);
|
|
||||||
ASSERT_REG_POSITION(semaphore_sequence, 0x6);
|
|
||||||
ASSERT_REG_POSITION(semaphore_trigger, 0x7);
|
|
||||||
ASSERT_REG_POSITION(reference_count, 0x14);
|
|
||||||
ASSERT_REG_POSITION(semaphore_acquire, 0x1A);
|
|
||||||
ASSERT_REG_POSITION(semaphore_release, 0x1B);
|
|
||||||
ASSERT_REG_POSITION(fence_value, 0x1C);
|
|
||||||
ASSERT_REG_POSITION(fence_action, 0x1D);
|
|
||||||
|
|
||||||
ASSERT_REG_POSITION(acquire_mode, 0x100);
|
|
||||||
ASSERT_REG_POSITION(acquire_source, 0x101);
|
|
||||||
ASSERT_REG_POSITION(acquire_active, 0x102);
|
|
||||||
ASSERT_REG_POSITION(acquire_timeout, 0x103);
|
|
||||||
ASSERT_REG_POSITION(acquire_value, 0x104);
|
|
||||||
|
|
||||||
#undef ASSERT_REG_POSITION
|
|
||||||
|
|
||||||
} // namespace Tegra
|
} // namespace Tegra
|
||||||
|
@ -130,9 +130,6 @@ public:
|
|||||||
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
|
/// Notify rasterizer that any caches of the specified region should be flushed and invalidated
|
||||||
void FlushAndInvalidateRegion(VAddr addr, u64 size);
|
void FlushAndInvalidateRegion(VAddr addr, u64 size);
|
||||||
|
|
||||||
// Stops the GPU execution and waits for the GPU to finish working
|
|
||||||
void ShutDown();
|
|
||||||
|
|
||||||
void OnCommandListEnd();
|
void OnCommandListEnd();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "shader_recompiler/environment.h"
|
#include "shader_recompiler/environment.h"
|
||||||
|
#include "video_core/engines/kepler_compute.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/shader_environment.h"
|
#include "video_core/shader_environment.h"
|
||||||
#include "video_core/textures/texture.h"
|
#include "video_core/textures/texture.h"
|
||||||
|
@ -5,13 +5,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <atomic>
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <span>
|
#include <span>
|
||||||
|
#include <stop_token>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -19,9 +19,7 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/unique_function.h"
|
#include "common/unique_function.h"
|
||||||
#include "shader_recompiler/environment.h"
|
#include "shader_recompiler/environment.h"
|
||||||
#include "video_core/engines/kepler_compute.h"
|
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/textures/texture.h"
|
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class Memorymanager;
|
class Memorymanager;
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/literals.h"
|
#include "common/literals.h"
|
||||||
|
Loading…
Reference in New Issue
Block a user