forked from ShuriZma/suyu
NVDRV: Refactor Host1x
This commit is contained in:
parent
668e80a9f4
commit
2931101e6f
|
@ -216,7 +216,7 @@ struct System::Impl {
|
||||||
|
|
||||||
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
telemetry_session = std::make_unique<Core::TelemetrySession>();
|
||||||
|
|
||||||
host1x_core = std::make_unique<Tegra::Host1x::Host1x>();
|
host1x_core = std::make_unique<Tegra::Host1x::Host1x>(system);
|
||||||
gpu_core = VideoCore::CreateGPU(emu_window, system);
|
gpu_core = VideoCore::CreateGPU(emu_window, system);
|
||||||
if (!gpu_core) {
|
if (!gpu_core) {
|
||||||
return SystemResultStatus::ErrorVideoCore;
|
return SystemResultStatus::ErrorVideoCore;
|
||||||
|
|
|
@ -6,18 +6,18 @@
|
||||||
#include "core/hle/service/nvdrv/core/container.h"
|
#include "core/hle/service/nvdrv/core/container.h"
|
||||||
#include "core/hle/service/nvdrv/core/nvmap.h"
|
#include "core/hle/service/nvdrv/core/nvmap.h"
|
||||||
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/host1x/host1x.h"
|
||||||
|
|
||||||
namespace Service::Nvidia::NvCore {
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
struct ContainerImpl {
|
struct ContainerImpl {
|
||||||
ContainerImpl(Tegra::GPU& gpu_) : file{}, manager{gpu_} {}
|
ContainerImpl(Tegra::Host1x::Host1x& host1x_) : file{host1x_}, manager{host1x_} {}
|
||||||
NvMap file;
|
NvMap file;
|
||||||
SyncpointManager manager;
|
SyncpointManager manager;
|
||||||
};
|
};
|
||||||
|
|
||||||
Container::Container(Tegra::GPU& gpu_) {
|
Container::Container(Tegra::Host1x::Host1x& host1x_) {
|
||||||
impl = std::make_unique<ContainerImpl>(gpu_);
|
impl = std::make_unique<ContainerImpl>(host1x_);
|
||||||
}
|
}
|
||||||
|
|
||||||
Container::~Container() = default;
|
Container::~Container() = default;
|
||||||
|
|
|
@ -8,8 +8,12 @@
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
}
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
|
} // namespace Tegra
|
||||||
|
|
||||||
namespace Service::Nvidia::NvCore {
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
|
@ -20,7 +24,7 @@ struct ContainerImpl;
|
||||||
|
|
||||||
class Container {
|
class Container {
|
||||||
public:
|
public:
|
||||||
Container(Tegra::GPU& gpu_);
|
Container(Tegra::Host1x::Host1x& host1x);
|
||||||
~Container();
|
~Container();
|
||||||
|
|
||||||
NvMap& GetNvMapFile();
|
NvMap& GetNvMapFile();
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/service/nvdrv/core/nvmap.h"
|
#include "core/hle/service/nvdrv/core/nvmap.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
|
|
||||||
using Core::Memory::YUZU_PAGESIZE;
|
using Core::Memory::YUZU_PAGESIZE;
|
||||||
|
|
||||||
|
@ -61,7 +62,7 @@ NvResult NvMap::Handle::Duplicate(bool internal_session) {
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvMap::NvMap() = default;
|
NvMap::NvMap(Tegra::Host1x::Host1x& host1x_) : host1x{host1x_} {}
|
||||||
|
|
||||||
void NvMap::AddHandle(std::shared_ptr<Handle> handle_description) {
|
void NvMap::AddHandle(std::shared_ptr<Handle> handle_description) {
|
||||||
std::scoped_lock lock(handles_lock);
|
std::scoped_lock lock(handles_lock);
|
||||||
|
@ -77,12 +78,11 @@ void NvMap::UnmapHandle(Handle& handle_description) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free and unmap the handle from the SMMU
|
// Free and unmap the handle from the SMMU
|
||||||
/*
|
host1x.MemoryManager().Unmap(static_cast<GPUVAddr>(handle_description.pin_virt_address),
|
||||||
state.soc->smmu.Unmap(handle_description.pin_virt_address,
|
handle_description.aligned_size);
|
||||||
static_cast<u32>(handle_description.aligned_size));
|
host1x.Allocator().Free(handle_description.pin_virt_address,
|
||||||
smmuAllocator.Free(handle_description.pin_virt_address,
|
static_cast<u32>(handle_description.aligned_size));
|
||||||
static_cast<u32>(handle_description.aligned_size)); handle_description.pin_virt_address = 0;
|
handle_description.pin_virt_address = 0;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NvMap::TryRemoveHandle(const Handle& handle_description) {
|
bool NvMap::TryRemoveHandle(const Handle& handle_description) {
|
||||||
|
@ -131,12 +131,9 @@ VAddr NvMap::GetHandleAddress(Handle::Id handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
|
u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
|
||||||
UNIMPLEMENTED_MSG("pinning");
|
|
||||||
return 0;
|
|
||||||
/*
|
|
||||||
auto handle_description{GetHandle(handle)};
|
auto handle_description{GetHandle(handle)};
|
||||||
if (!handle_description)
|
if (!handle_description) [[unlikely]]
|
||||||
[[unlikely]] return 0;
|
return 0;
|
||||||
|
|
||||||
std::scoped_lock lock(handle_description->mutex);
|
std::scoped_lock lock(handle_description->mutex);
|
||||||
if (!handle_description->pins) {
|
if (!handle_description->pins) {
|
||||||
|
@ -157,8 +154,10 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
|
||||||
|
|
||||||
// If not then allocate some space and map it
|
// If not then allocate some space and map it
|
||||||
u32 address{};
|
u32 address{};
|
||||||
|
auto& smmu_allocator = host1x.Allocator();
|
||||||
|
auto& smmu_memory_manager = host1x.MemoryManager();
|
||||||
while (!(address =
|
while (!(address =
|
||||||
smmuAllocator.Allocate(static_cast<u32>(handle_description->aligned_size)))) {
|
smmu_allocator.Allocate(static_cast<u32>(handle_description->aligned_size)))) {
|
||||||
// Free handles until the allocation succeeds
|
// Free handles until the allocation succeeds
|
||||||
std::scoped_lock queueLock(unmap_queue_lock);
|
std::scoped_lock queueLock(unmap_queue_lock);
|
||||||
if (auto freeHandleDesc{unmap_queue.front()}) {
|
if (auto freeHandleDesc{unmap_queue.front()}) {
|
||||||
|
@ -172,19 +171,16 @@ u32 NvMap::PinHandle(NvMap::Handle::Id handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state.soc->smmu.Map(address, handle_description->GetPointer(),
|
smmu_memory_manager.Map(static_cast<GPUVAddr>(address), handle_description->address,
|
||||||
static_cast<u32>(handle_description->aligned_size));
|
handle_description->aligned_size);
|
||||||
handle_description->pin_virt_address = address;
|
handle_description->pin_virt_address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_description->pins++;
|
handle_description->pins++;
|
||||||
return handle_description->pin_virt_address;
|
return handle_description->pin_virt_address;
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NvMap::UnpinHandle(Handle::Id handle) {
|
void NvMap::UnpinHandle(Handle::Id handle) {
|
||||||
UNIMPLEMENTED_MSG("Unpinning");
|
|
||||||
/*
|
|
||||||
auto handle_description{GetHandle(handle)};
|
auto handle_description{GetHandle(handle)};
|
||||||
if (!handle_description)
|
if (!handle_description)
|
||||||
return;
|
return;
|
||||||
|
@ -199,7 +195,6 @@ void NvMap::UnpinHandle(Handle::Id handle) {
|
||||||
unmap_queue.push_back(handle_description);
|
unmap_queue.push_back(handle_description);
|
||||||
handle_description->unmap_queue_entry = std::prev(unmap_queue.end());
|
handle_description->unmap_queue_entry = std::prev(unmap_queue.end());
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {
|
std::optional<NvMap::FreeInfo> NvMap::FreeHandle(Handle::Id handle, bool internal_session) {
|
||||||
|
|
|
@ -15,6 +15,14 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/service/nvdrv/nvdata.h"
|
#include "core/hle/service/nvdrv/nvdata.h"
|
||||||
|
|
||||||
|
namespace Tegra {
|
||||||
|
|
||||||
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
|
} // namespace Tegra
|
||||||
|
|
||||||
namespace Service::Nvidia::NvCore {
|
namespace Service::Nvidia::NvCore {
|
||||||
/**
|
/**
|
||||||
* @brief The nvmap core class holds the global state for nvmap and provides methods to manage
|
* @brief The nvmap core class holds the global state for nvmap and provides methods to manage
|
||||||
|
@ -90,15 +98,17 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::list<std::shared_ptr<Handle>> unmap_queue;
|
std::list<std::shared_ptr<Handle>> unmap_queue{};
|
||||||
std::mutex unmap_queue_lock; //!< Protects access to `unmap_queue`
|
std::mutex unmap_queue_lock{}; //!< Protects access to `unmap_queue`
|
||||||
|
|
||||||
std::unordered_map<Handle::Id, std::shared_ptr<Handle>> handles; //!< Main owning map of handles
|
std::unordered_map<Handle::Id, std::shared_ptr<Handle>>
|
||||||
|
handles{}; //!< Main owning map of handles
|
||||||
std::mutex handles_lock; //!< Protects access to `handles`
|
std::mutex handles_lock; //!< Protects access to `handles`
|
||||||
|
|
||||||
static constexpr u32 HandleIdIncrement{
|
static constexpr u32 HandleIdIncrement{
|
||||||
4}; //!< Each new handle ID is an increment of 4 from the previous
|
4}; //!< Each new handle ID is an increment of 4 from the previous
|
||||||
std::atomic<u32> next_handle_id{HandleIdIncrement};
|
std::atomic<u32> next_handle_id{HandleIdIncrement};
|
||||||
|
Tegra::Host1x::Host1x& host1x;
|
||||||
|
|
||||||
void AddHandle(std::shared_ptr<Handle> handle);
|
void AddHandle(std::shared_ptr<Handle> handle);
|
||||||
|
|
||||||
|
@ -125,7 +135,7 @@ public:
|
||||||
bool was_uncached; //!< If the handle was allocated as uncached
|
bool was_uncached; //!< If the handle was allocated as uncached
|
||||||
};
|
};
|
||||||
|
|
||||||
NvMap();
|
NvMap(Tegra::Host1x::Host1x& host1x);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates an unallocated handle of the given size
|
* @brief Creates an unallocated handle of the given size
|
||||||
|
|
|
@ -3,16 +3,16 @@
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/host1x/host1x.h"
|
||||||
|
|
||||||
namespace Service::Nvidia::NvCore {
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
SyncpointManager::SyncpointManager(Tegra::GPU& gpu_) : gpu{gpu_} {}
|
SyncpointManager::SyncpointManager(Tegra::Host1x::Host1x& host1x_) : host1x{host1x_} {}
|
||||||
|
|
||||||
SyncpointManager::~SyncpointManager() = default;
|
SyncpointManager::~SyncpointManager() = default;
|
||||||
|
|
||||||
u32 SyncpointManager::RefreshSyncpoint(u32 syncpoint_id) {
|
u32 SyncpointManager::RefreshSyncpoint(u32 syncpoint_id) {
|
||||||
syncpoints[syncpoint_id].min = gpu.GetSyncpointValue(syncpoint_id);
|
syncpoints[syncpoint_id].min = host1x.GetSyncpointManager().GetHostSyncpointValue(syncpoint_id);
|
||||||
return GetSyncpointMin(syncpoint_id);
|
return GetSyncpointMin(syncpoint_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,14 +10,18 @@
|
||||||
#include "core/hle/service/nvdrv/nvdata.h"
|
#include "core/hle/service/nvdrv/nvdata.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
}
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
|
} // namespace Tegra
|
||||||
|
|
||||||
namespace Service::Nvidia::NvCore {
|
namespace Service::Nvidia::NvCore {
|
||||||
|
|
||||||
class SyncpointManager final {
|
class SyncpointManager final {
|
||||||
public:
|
public:
|
||||||
explicit SyncpointManager(Tegra::GPU& gpu_);
|
explicit SyncpointManager(Tegra::Host1x::Host1x& host1x);
|
||||||
~SyncpointManager();
|
~SyncpointManager();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,7 +82,7 @@ private:
|
||||||
|
|
||||||
std::array<Syncpoint, MaxSyncPoints> syncpoints{};
|
std::array<Syncpoint, MaxSyncPoints> syncpoints{};
|
||||||
|
|
||||||
Tegra::GPU& gpu;
|
Tegra::Host1x::Host1x& host1x;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::Nvidia::NvCore
|
} // namespace Service::Nvidia::NvCore
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
#include "core/hle/service/nvdrv/core/syncpoint_manager.h"
|
||||||
#include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h"
|
#include "core/hle/service/nvdrv/devices/nvhost_nvdec_common.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
#include "video_core/renderer_base.h"
|
#include "video_core/renderer_base.h"
|
||||||
|
|
||||||
|
@ -140,29 +141,8 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
|
||||||
|
|
||||||
SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
|
SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
|
||||||
|
|
||||||
auto& gpu = system.GPU();
|
|
||||||
|
|
||||||
for (auto& cmd_buffer : cmd_buffer_handles) {
|
for (auto& cmd_buffer : cmd_buffer_handles) {
|
||||||
auto object{nvmap.GetHandle(cmd_buffer.map_handle)};
|
cmd_buffer.map_address = nvmap.PinHandle(cmd_buffer.map_handle);
|
||||||
if (!object) {
|
|
||||||
LOG_ERROR(Service_NVDRV, "invalid cmd_buffer nvmap_handle={:X}", cmd_buffer.map_handle);
|
|
||||||
std::memcpy(output.data(), ¶ms, output.size());
|
|
||||||
return NvResult::InvalidState;
|
|
||||||
}
|
|
||||||
if (object->dma_map_addr == 0) {
|
|
||||||
// NVDEC and VIC memory is in the 32-bit address space
|
|
||||||
// MapAllocate32 will attempt to map a lower 32-bit value in the shared gpu memory space
|
|
||||||
const GPUVAddr low_addr =
|
|
||||||
gpu.MemoryManager().MapAllocate32(object->address, object->size);
|
|
||||||
object->dma_map_addr = static_cast<u32>(low_addr);
|
|
||||||
// Ensure that the dma_map_addr is indeed in the lower 32-bit address space.
|
|
||||||
ASSERT(object->dma_map_addr == low_addr);
|
|
||||||
}
|
|
||||||
if (!object->dma_map_addr) {
|
|
||||||
LOG_ERROR(Service_NVDRV, "failed to map size={}", object->size);
|
|
||||||
} else {
|
|
||||||
cmd_buffer.map_address = static_cast<u32_le>(object->dma_map_addr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer));
|
std::memcpy(output.data(), ¶ms, sizeof(IoctlMapBuffer));
|
||||||
std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(),
|
std::memcpy(output.data() + sizeof(IoctlMapBuffer), cmd_buffer_handles.data(),
|
||||||
|
@ -172,11 +152,16 @@ NvResult nvhost_nvdec_common::MapBuffer(const std::vector<u8>& input, std::vecto
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
|
NvResult nvhost_nvdec_common::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output) {
|
||||||
// This is intntionally stubbed.
|
IoctlMapBuffer params{};
|
||||||
// Skip unmapping buffers here, as to not break the continuity of the VP9 reference frame
|
std::memcpy(¶ms, input.data(), sizeof(IoctlMapBuffer));
|
||||||
// addresses, and risk invalidating data before the async GPU thread is done with it
|
std::vector<MapBufferEntry> cmd_buffer_handles(params.num_entries);
|
||||||
|
|
||||||
|
SliceVectors(input, cmd_buffer_handles, params.num_entries, sizeof(IoctlMapBuffer));
|
||||||
|
for (auto& cmd_buffer : cmd_buffer_handles) {
|
||||||
|
nvmap.UnpinHandle(cmd_buffer.map_handle);
|
||||||
|
}
|
||||||
|
|
||||||
std::memset(output.data(), 0, output.size());
|
std::memset(output.data(), 0, output.size());
|
||||||
LOG_DEBUG(Service_NVDRV, "(STUBBED) called");
|
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
|
||||||
}
|
}
|
||||||
|
|
||||||
Module::Module(Core::System& system)
|
Module::Module(Core::System& system)
|
||||||
: service_context{system, "nvdrv"}, events_interface{*this}, container{system.GPU()} {
|
: service_context{system, "nvdrv"}, events_interface{*this}, container{system.Host1x()} {
|
||||||
builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) {
|
builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) {
|
||||||
std::shared_ptr<Devices::nvdevice> device =
|
std::shared_ptr<Devices::nvdevice> device =
|
||||||
std::make_shared<Devices::nvhost_as_gpu>(system, *this, container);
|
std::make_shared<Devices::nvhost_as_gpu>(system, *this, container);
|
||||||
|
|
|
@ -56,6 +56,8 @@ add_library(video_core STATIC
|
||||||
host1x/codecs/vp9_types.h
|
host1x/codecs/vp9_types.h
|
||||||
host1x/control.cpp
|
host1x/control.cpp
|
||||||
host1x/control.h
|
host1x/control.h
|
||||||
|
host1x/host1x.cpp
|
||||||
|
host1x/host1x.h
|
||||||
host1x/nvdec.cpp
|
host1x/nvdec.cpp
|
||||||
host1x/nvdec.h
|
host1x/nvdec.h
|
||||||
host1x/nvdec_common.h
|
host1x/nvdec_common.h
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include <bit>
|
#include <bit>
|
||||||
#include "video_core/cdma_pusher.h"
|
#include "video_core/cdma_pusher.h"
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/gpu.h"
|
|
||||||
#include "video_core/host1x/control.h"
|
#include "video_core/host1x/control.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/host1x/nvdec.h"
|
#include "video_core/host1x/nvdec.h"
|
||||||
#include "video_core/host1x/nvdec_common.h"
|
#include "video_core/host1x/nvdec_common.h"
|
||||||
#include "video_core/host1x/sync_manager.h"
|
#include "video_core/host1x/sync_manager.h"
|
||||||
|
@ -13,11 +13,11 @@
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
CDmaPusher::CDmaPusher(GPU& gpu_)
|
CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_)
|
||||||
: gpu{gpu_}, nvdec_processor(std::make_shared<Host1x::Nvdec>(gpu)),
|
: host1x{host1x_}, nvdec_processor(std::make_shared<Host1x::Nvdec>(host1x)),
|
||||||
vic_processor(std::make_unique<Host1x::Vic>(gpu, nvdec_processor)),
|
vic_processor(std::make_unique<Host1x::Vic>(host1x, nvdec_processor)),
|
||||||
host1x_processor(std::make_unique<Host1x::Control>(gpu)),
|
host1x_processor(std::make_unique<Host1x::Control>(host1x)),
|
||||||
sync_manager(std::make_unique<Host1x::SyncptIncrManager>(gpu)) {}
|
sync_manager(std::make_unique<Host1x::SyncptIncrManager>(host1x)) {}
|
||||||
|
|
||||||
CDmaPusher::~CDmaPusher() = default;
|
CDmaPusher::~CDmaPusher() = default;
|
||||||
|
|
||||||
|
|
|
@ -12,10 +12,9 @@
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
||||||
class GPU;
|
|
||||||
|
|
||||||
namespace Host1x {
|
namespace Host1x {
|
||||||
class Control;
|
class Control;
|
||||||
|
class Host1x;
|
||||||
class Nvdec;
|
class Nvdec;
|
||||||
class SyncptIncrManager;
|
class SyncptIncrManager;
|
||||||
class Vic;
|
class Vic;
|
||||||
|
@ -91,7 +90,7 @@ enum class ThiMethod : u32 {
|
||||||
|
|
||||||
class CDmaPusher {
|
class CDmaPusher {
|
||||||
public:
|
public:
|
||||||
explicit CDmaPusher(GPU& gpu_);
|
explicit CDmaPusher(Host1x::Host1x& host1x);
|
||||||
~CDmaPusher();
|
~CDmaPusher();
|
||||||
|
|
||||||
/// Process the command entry
|
/// Process the command entry
|
||||||
|
@ -104,7 +103,7 @@ private:
|
||||||
/// Write arguments value to the ThiRegisters member at the specified offset
|
/// Write arguments value to the ThiRegisters member at the specified offset
|
||||||
void ThiStateWrite(ThiRegisters& state, u32 offset, u32 argument);
|
void ThiStateWrite(ThiRegisters& state, u32 offset, u32 argument);
|
||||||
|
|
||||||
GPU& gpu;
|
Host1x::Host1x& host1x;
|
||||||
std::shared_ptr<Tegra::Host1x::Nvdec> nvdec_processor;
|
std::shared_ptr<Tegra::Host1x::Nvdec> nvdec_processor;
|
||||||
std::unique_ptr<Tegra::Host1x::Vic> vic_processor;
|
std::unique_ptr<Tegra::Host1x::Vic> vic_processor;
|
||||||
std::unique_ptr<Tegra::Host1x::Control> host1x_processor;
|
std::unique_ptr<Tegra::Host1x::Control> host1x_processor;
|
||||||
|
|
|
@ -83,19 +83,11 @@ struct GPU::Impl {
|
||||||
UNIMPLEMENTED();
|
UNIMPLEMENTED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateHost1xChannel() {
|
|
||||||
if (host1x_channel) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
host1x_channel = CreateChannel(0);
|
|
||||||
host1x_channel->memory_manager = std::make_shared<Tegra::MemoryManager>(system);
|
|
||||||
InitChannel(*host1x_channel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Binds a renderer to the GPU.
|
/// Binds a renderer to the GPU.
|
||||||
void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
|
void BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) {
|
||||||
renderer = std::move(renderer_);
|
renderer = std::move(renderer_);
|
||||||
rasterizer = renderer->ReadRasterizer();
|
rasterizer = renderer->ReadRasterizer();
|
||||||
|
host1x.MemoryManager().BindRasterizer(rasterizer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Flush all current written commands into the host GPU for execution.
|
/// Flush all current written commands into the host GPU for execution.
|
||||||
|
@ -173,12 +165,6 @@ struct GPU::Impl {
|
||||||
return *current_channel->kepler_compute;
|
return *current_channel->kepler_compute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the GPU memory manager.
|
|
||||||
[[nodiscard]] Tegra::MemoryManager& MemoryManager() {
|
|
||||||
CreateHost1xChannel();
|
|
||||||
return *host1x_channel->memory_manager;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a reference to the GPU DMA pusher.
|
/// Returns a reference to the GPU DMA pusher.
|
||||||
[[nodiscard]] Tegra::DmaPusher& DmaPusher() {
|
[[nodiscard]] Tegra::DmaPusher& DmaPusher() {
|
||||||
ASSERT(current_channel);
|
ASSERT(current_channel);
|
||||||
|
@ -299,7 +285,7 @@ struct GPU::Impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!cdma_pushers.contains(id)) {
|
if (!cdma_pushers.contains(id)) {
|
||||||
cdma_pushers.insert_or_assign(id, std::make_unique<Tegra::CDmaPusher>(gpu));
|
cdma_pushers.insert_or_assign(id, std::make_unique<Tegra::CDmaPusher>(host1x));
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubmitCommandBuffer would make the nvdec operations async, this is not currently working
|
// SubmitCommandBuffer would make the nvdec operations async, this is not currently working
|
||||||
|
@ -389,7 +375,6 @@ struct GPU::Impl {
|
||||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||||
const bool use_nvdec;
|
const bool use_nvdec;
|
||||||
|
|
||||||
std::shared_ptr<Control::ChannelState> host1x_channel;
|
|
||||||
s32 new_channel_id{1};
|
s32 new_channel_id{1};
|
||||||
/// Shader build notifier
|
/// Shader build notifier
|
||||||
std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
|
std::unique_ptr<VideoCore::ShaderNotify> shader_notify;
|
||||||
|
@ -510,14 +495,6 @@ const Engines::KeplerCompute& GPU::KeplerCompute() const {
|
||||||
return impl->KeplerCompute();
|
return impl->KeplerCompute();
|
||||||
}
|
}
|
||||||
|
|
||||||
Tegra::MemoryManager& GPU::MemoryManager() {
|
|
||||||
return impl->MemoryManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
const Tegra::MemoryManager& GPU::MemoryManager() const {
|
|
||||||
return impl->MemoryManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
Tegra::DmaPusher& GPU::DmaPusher() {
|
Tegra::DmaPusher& GPU::DmaPusher() {
|
||||||
return impl->DmaPusher();
|
return impl->DmaPusher();
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,12 +153,6 @@ public:
|
||||||
/// Returns a reference to the KeplerCompute GPU engine.
|
/// Returns a reference to the KeplerCompute GPU engine.
|
||||||
[[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const;
|
[[nodiscard]] const Engines::KeplerCompute& KeplerCompute() const;
|
||||||
|
|
||||||
/// Returns a reference to the GPU memory manager.
|
|
||||||
[[nodiscard]] Tegra::MemoryManager& MemoryManager();
|
|
||||||
|
|
||||||
/// Returns a const reference to the GPU memory manager.
|
|
||||||
[[nodiscard]] const Tegra::MemoryManager& MemoryManager() const;
|
|
||||||
|
|
||||||
/// Returns a reference to the GPU DMA pusher.
|
/// Returns a reference to the GPU DMA pusher.
|
||||||
[[nodiscard]] Tegra::DmaPusher& DmaPusher();
|
[[nodiscard]] Tegra::DmaPusher& DmaPusher();
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "video_core/gpu.h"
|
|
||||||
#include "video_core/host1x/codecs/codec.h"
|
#include "video_core/host1x/codecs/codec.h"
|
||||||
#include "video_core/host1x/codecs/h264.h"
|
#include "video_core/host1x/codecs/h264.h"
|
||||||
#include "video_core/host1x/codecs/vp8.h"
|
#include "video_core/host1x/codecs/vp8.h"
|
||||||
#include "video_core/host1x/codecs/vp9.h"
|
#include "video_core/host1x/codecs/vp9.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -73,10 +73,10 @@ void AVFrameDeleter(AVFrame* ptr) {
|
||||||
av_frame_free(&ptr);
|
av_frame_free(&ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Codec::Codec(GPU& gpu_, const Host1x::NvdecCommon::NvdecRegisters& regs)
|
Codec::Codec(Host1x::Host1x& host1x_, const Host1x::NvdecCommon::NvdecRegisters& regs)
|
||||||
: gpu(gpu_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(gpu)),
|
: host1x(host1x_), state{regs}, h264_decoder(std::make_unique<Decoder::H264>(host1x)),
|
||||||
vp8_decoder(std::make_unique<Decoder::VP8>(gpu)),
|
vp8_decoder(std::make_unique<Decoder::VP8>(host1x)),
|
||||||
vp9_decoder(std::make_unique<Decoder::VP9>(gpu)) {}
|
vp9_decoder(std::make_unique<Decoder::VP9>(host1x)) {}
|
||||||
|
|
||||||
Codec::~Codec() {
|
Codec::~Codec() {
|
||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
|
|
|
@ -21,7 +21,6 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
|
||||||
void AVFrameDeleter(AVFrame* ptr);
|
void AVFrameDeleter(AVFrame* ptr);
|
||||||
using AVFramePtr = std::unique_ptr<AVFrame, decltype(&AVFrameDeleter)>;
|
using AVFramePtr = std::unique_ptr<AVFrame, decltype(&AVFrameDeleter)>;
|
||||||
|
@ -32,9 +31,13 @@ class VP8;
|
||||||
class VP9;
|
class VP9;
|
||||||
} // namespace Decoder
|
} // namespace Decoder
|
||||||
|
|
||||||
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
class Codec {
|
class Codec {
|
||||||
public:
|
public:
|
||||||
explicit Codec(GPU& gpu, const Host1x::NvdecCommon::NvdecRegisters& regs);
|
explicit Codec(Host1x::Host1x& host1x, const Host1x::NvdecCommon::NvdecRegisters& regs);
|
||||||
~Codec();
|
~Codec();
|
||||||
|
|
||||||
/// Initialize the codec, returning success or failure
|
/// Initialize the codec, returning success or failure
|
||||||
|
@ -69,7 +72,7 @@ private:
|
||||||
AVCodecContext* av_codec_ctx{nullptr};
|
AVCodecContext* av_codec_ctx{nullptr};
|
||||||
AVBufferRef* av_gpu_decoder{nullptr};
|
AVBufferRef* av_gpu_decoder{nullptr};
|
||||||
|
|
||||||
GPU& gpu;
|
Host1x::Host1x& host1x;
|
||||||
const Host1x::NvdecCommon::NvdecRegisters& state;
|
const Host1x::NvdecCommon::NvdecRegisters& state;
|
||||||
std::unique_ptr<Decoder::H264> h264_decoder;
|
std::unique_ptr<Decoder::H264> h264_decoder;
|
||||||
std::unique_ptr<Decoder::VP8> vp8_decoder;
|
std::unique_ptr<Decoder::VP8> vp8_decoder;
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
#include <bit>
|
#include <bit>
|
||||||
|
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "video_core/gpu.h"
|
|
||||||
#include "video_core/host1x/codecs/h264.h"
|
#include "video_core/host1x/codecs/h264.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
||||||
namespace Tegra::Decoder {
|
namespace Tegra::Decoder {
|
||||||
|
@ -24,19 +24,20 @@ constexpr std::array<u8, 16> zig_zag_scan{
|
||||||
};
|
};
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
H264::H264(GPU& gpu_) : gpu(gpu_) {}
|
H264::H264(Host1x::Host1x& host1x_) : host1x{host1x_} {}
|
||||||
|
|
||||||
H264::~H264() = default;
|
H264::~H264() = default;
|
||||||
|
|
||||||
const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state,
|
const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state,
|
||||||
bool is_first_frame) {
|
bool is_first_frame) {
|
||||||
H264DecoderContext context;
|
H264DecoderContext context;
|
||||||
gpu.MemoryManager().ReadBlock(state.picture_info_offset, &context, sizeof(H264DecoderContext));
|
host1x.MemoryManager().ReadBlock(state.picture_info_offset, &context,
|
||||||
|
sizeof(H264DecoderContext));
|
||||||
|
|
||||||
const s64 frame_number = context.h264_parameter_set.frame_number.Value();
|
const s64 frame_number = context.h264_parameter_set.frame_number.Value();
|
||||||
if (!is_first_frame && frame_number != 0) {
|
if (!is_first_frame && frame_number != 0) {
|
||||||
frame.resize(context.stream_len);
|
frame.resize(context.stream_len);
|
||||||
gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size());
|
host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, frame.data(), frame.size());
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +156,8 @@ const std::vector<u8>& H264::ComposeFrame(const Host1x::NvdecCommon::NvdecRegist
|
||||||
frame.resize(encoded_header.size() + context.stream_len);
|
frame.resize(encoded_header.size() + context.stream_len);
|
||||||
std::memcpy(frame.data(), encoded_header.data(), encoded_header.size());
|
std::memcpy(frame.data(), encoded_header.data(), encoded_header.size());
|
||||||
|
|
||||||
gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset,
|
host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset,
|
||||||
frame.data() + encoded_header.size(), context.stream_len);
|
frame.data() + encoded_header.size(), context.stream_len);
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,11 @@
|
||||||
#include "video_core/host1x/nvdec_common.h"
|
#include "video_core/host1x/nvdec_common.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
namespace Decoder {
|
namespace Decoder {
|
||||||
|
|
||||||
class H264BitWriter {
|
class H264BitWriter {
|
||||||
|
@ -55,7 +59,7 @@ private:
|
||||||
|
|
||||||
class H264 {
|
class H264 {
|
||||||
public:
|
public:
|
||||||
explicit H264(GPU& gpu);
|
explicit H264(Host1x::Host1x& host1x);
|
||||||
~H264();
|
~H264();
|
||||||
|
|
||||||
/// Compose the H264 frame for FFmpeg decoding
|
/// Compose the H264 frame for FFmpeg decoding
|
||||||
|
@ -64,7 +68,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<u8> frame;
|
std::vector<u8> frame;
|
||||||
GPU& gpu;
|
Host1x::Host1x& host1x;
|
||||||
|
|
||||||
struct H264ParameterSet {
|
struct H264ParameterSet {
|
||||||
s32 log2_max_pic_order_cnt_lsb_minus4; ///< 0x00
|
s32 log2_max_pic_order_cnt_lsb_minus4; ///< 0x00
|
||||||
|
|
|
@ -3,18 +3,18 @@
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "video_core/gpu.h"
|
|
||||||
#include "video_core/host1x/codecs/vp8.h"
|
#include "video_core/host1x/codecs/vp8.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
||||||
namespace Tegra::Decoder {
|
namespace Tegra::Decoder {
|
||||||
VP8::VP8(GPU& gpu_) : gpu(gpu_) {}
|
VP8::VP8(Host1x::Host1x& host1x_) : host1x{host1x_} {}
|
||||||
|
|
||||||
VP8::~VP8() = default;
|
VP8::~VP8() = default;
|
||||||
|
|
||||||
const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) {
|
const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegisters& state) {
|
||||||
VP8PictureInfo info;
|
VP8PictureInfo info;
|
||||||
gpu.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo));
|
host1x.MemoryManager().ReadBlock(state.picture_info_offset, &info, sizeof(VP8PictureInfo));
|
||||||
|
|
||||||
const bool is_key_frame = info.key_frame == 1u;
|
const bool is_key_frame = info.key_frame == 1u;
|
||||||
const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size);
|
const auto bitstream_size = static_cast<size_t>(info.vld_buffer_size);
|
||||||
|
@ -45,7 +45,7 @@ const std::vector<u8>& VP8::ComposeFrame(const Host1x::NvdecCommon::NvdecRegiste
|
||||||
frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f));
|
frame[9] = static_cast<u8>(((info.frame_height >> 8) & 0x3f));
|
||||||
}
|
}
|
||||||
const u64 bitstream_offset = state.frame_bitstream_offset;
|
const u64 bitstream_offset = state.frame_bitstream_offset;
|
||||||
gpu.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size);
|
host1x.MemoryManager().ReadBlock(bitstream_offset, frame.data() + header_size, bitstream_size);
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,16 @@
|
||||||
#include "video_core/host1x/nvdec_common.h"
|
#include "video_core/host1x/nvdec_common.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
namespace Decoder {
|
namespace Decoder {
|
||||||
|
|
||||||
class VP8 {
|
class VP8 {
|
||||||
public:
|
public:
|
||||||
explicit VP8(GPU& gpu);
|
explicit VP8(Host1x::Host1x& host1x);
|
||||||
~VP8();
|
~VP8();
|
||||||
|
|
||||||
/// Compose the VP8 frame for FFmpeg decoding
|
/// Compose the VP8 frame for FFmpeg decoding
|
||||||
|
@ -25,7 +29,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<u8> frame;
|
std::vector<u8> frame;
|
||||||
GPU& gpu;
|
Host1x::Host1x& host1x;
|
||||||
|
|
||||||
struct VP8PictureInfo {
|
struct VP8PictureInfo {
|
||||||
INSERT_PADDING_WORDS_NOINIT(14);
|
INSERT_PADDING_WORDS_NOINIT(14);
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
#include <algorithm> // for std::copy
|
#include <algorithm> // for std::copy
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "video_core/gpu.h"
|
|
||||||
#include "video_core/host1x/codecs/vp9.h"
|
#include "video_core/host1x/codecs/vp9.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
|
||||||
namespace Tegra::Decoder {
|
namespace Tegra::Decoder {
|
||||||
|
@ -236,7 +236,7 @@ constexpr std::array<u8, 254> map_lut{
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
VP9::VP9(GPU& gpu_) : gpu{gpu_} {}
|
VP9::VP9(Host1x::Host1x& host1x_) : host1x{host1x_} {}
|
||||||
|
|
||||||
VP9::~VP9() = default;
|
VP9::~VP9() = default;
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ void VP9::WriteMvProbabilityUpdate(VpxRangeEncoder& writer, u8 new_prob, u8 old_
|
||||||
|
|
||||||
Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) {
|
Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters& state) {
|
||||||
PictureInfo picture_info;
|
PictureInfo picture_info;
|
||||||
gpu.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo));
|
host1x.MemoryManager().ReadBlock(state.picture_info_offset, &picture_info, sizeof(PictureInfo));
|
||||||
Vp9PictureInfo vp9_info = picture_info.Convert();
|
Vp9PictureInfo vp9_info = picture_info.Convert();
|
||||||
|
|
||||||
InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy);
|
InsertEntropy(state.vp9_entropy_probs_offset, vp9_info.entropy);
|
||||||
|
@ -372,17 +372,17 @@ Vp9PictureInfo VP9::GetVp9PictureInfo(const Host1x::NvdecCommon::NvdecRegisters&
|
||||||
|
|
||||||
void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) {
|
void VP9::InsertEntropy(u64 offset, Vp9EntropyProbs& dst) {
|
||||||
EntropyProbs entropy;
|
EntropyProbs entropy;
|
||||||
gpu.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs));
|
host1x.MemoryManager().ReadBlock(offset, &entropy, sizeof(EntropyProbs));
|
||||||
entropy.Convert(dst);
|
entropy.Convert(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vp9FrameContainer VP9::GetCurrentFrame(const Host1x::NvdecCommon::NvdecRegisters& state) {
|
Vp9FrameContainer VP9::GetCurrentFrame(const Host1x::NvdecCommon::NvdecRegisters& state) {
|
||||||
Vp9FrameContainer current_frame{};
|
Vp9FrameContainer current_frame{};
|
||||||
{
|
{
|
||||||
gpu.SyncGuestHost();
|
// gpu.SyncGuestHost(); epic, why?
|
||||||
current_frame.info = GetVp9PictureInfo(state);
|
current_frame.info = GetVp9PictureInfo(state);
|
||||||
current_frame.bit_stream.resize(current_frame.info.bitstream_size);
|
current_frame.bit_stream.resize(current_frame.info.bitstream_size);
|
||||||
gpu.MemoryManager().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(),
|
host1x.MemoryManager().ReadBlock(state.frame_bitstream_offset, current_frame.bit_stream.data(),
|
||||||
current_frame.info.bitstream_size);
|
current_frame.info.bitstream_size);
|
||||||
}
|
}
|
||||||
if (!next_frame.bit_stream.empty()) {
|
if (!next_frame.bit_stream.empty()) {
|
||||||
|
|
|
@ -12,7 +12,11 @@
|
||||||
#include "video_core/host1x/nvdec_common.h"
|
#include "video_core/host1x/nvdec_common.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
namespace Host1x {
|
||||||
|
class Host1x;
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
namespace Decoder {
|
namespace Decoder {
|
||||||
|
|
||||||
/// The VpxRangeEncoder, and VpxBitStreamWriter classes are used to compose the
|
/// The VpxRangeEncoder, and VpxBitStreamWriter classes are used to compose the
|
||||||
|
@ -106,7 +110,7 @@ private:
|
||||||
|
|
||||||
class VP9 {
|
class VP9 {
|
||||||
public:
|
public:
|
||||||
explicit VP9(GPU& gpu_);
|
explicit VP9(Host1x::Host1x& host1x);
|
||||||
~VP9();
|
~VP9();
|
||||||
|
|
||||||
VP9(const VP9&) = delete;
|
VP9(const VP9&) = delete;
|
||||||
|
@ -176,7 +180,7 @@ private:
|
||||||
[[nodiscard]] std::vector<u8> ComposeCompressedHeader();
|
[[nodiscard]] std::vector<u8> ComposeCompressedHeader();
|
||||||
[[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader();
|
[[nodiscard]] VpxBitStreamWriter ComposeUncompressedHeader();
|
||||||
|
|
||||||
GPU& gpu;
|
Host1x::Host1x& host1x;
|
||||||
std::vector<u8> frame;
|
std::vector<u8> frame;
|
||||||
|
|
||||||
std::array<s8, 4> loop_filter_ref_deltas{};
|
std::array<s8, 4> loop_filter_ref_deltas{};
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
|
||||||
namespace Decoder {
|
namespace Decoder {
|
||||||
struct Vp9FrameDimensions {
|
struct Vp9FrameDimensions {
|
||||||
|
|
|
@ -3,13 +3,12 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "video_core/gpu.h"
|
|
||||||
#include "video_core/host1x/control.h"
|
#include "video_core/host1x/control.h"
|
||||||
#include "video_core/host1x/host1x.h"
|
#include "video_core/host1x/host1x.h"
|
||||||
|
|
||||||
namespace Tegra::Host1x {
|
namespace Tegra::Host1x {
|
||||||
|
|
||||||
Control::Control(GPU& gpu_) : gpu(gpu_) {}
|
Control::Control(Host1x& host1x_) : host1x(host1x_) {}
|
||||||
|
|
||||||
Control::~Control() = default;
|
Control::~Control() = default;
|
||||||
|
|
||||||
|
@ -29,7 +28,7 @@ void Control::ProcessMethod(Method method, u32 argument) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Control::Execute(u32 data) {
|
void Control::Execute(u32 data) {
|
||||||
gpu.Host1x().GetSyncpointManager().WaitHost(data, syncpoint_value);
|
host1x.GetSyncpointManager().WaitHost(data, syncpoint_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Tegra::Host1x
|
} // namespace Tegra::Host1x
|
||||||
|
|
|
@ -8,10 +8,10 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
|
||||||
namespace Host1x {
|
namespace Host1x {
|
||||||
|
|
||||||
|
class Host1x;
|
||||||
class Nvdec;
|
class Nvdec;
|
||||||
|
|
||||||
class Control {
|
class Control {
|
||||||
|
@ -22,7 +22,7 @@ public:
|
||||||
WaitSyncpt32 = 0x50,
|
WaitSyncpt32 = 0x50,
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Control(GPU& gpu);
|
explicit Control(Host1x& host1x);
|
||||||
~Control();
|
~Control();
|
||||||
|
|
||||||
/// Writes the method into the state, Invoke Execute() if encountered
|
/// Writes the method into the state, Invoke Execute() if encountered
|
||||||
|
@ -33,7 +33,7 @@ private:
|
||||||
void Execute(u32 data);
|
void Execute(u32 data);
|
||||||
|
|
||||||
u32 syncpoint_value{};
|
u32 syncpoint_value{};
|
||||||
GPU& gpu;
|
Host1x& host1x;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Host1x
|
} // namespace Host1x
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
// Copyright 2022 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv3 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include "core/core.h"
|
||||||
|
#include "video_core/host1x/host1x.h"
|
||||||
|
|
||||||
|
namespace Tegra {
|
||||||
|
|
||||||
|
namespace Host1x {
|
||||||
|
|
||||||
|
Host1x::Host1x(Core::System& system_)
|
||||||
|
: system{system_}, syncpoint_manager{}, memory_manager{system, 32, 12},
|
||||||
|
allocator{std::make_unique<Common::FlatAllocator<u32, 0, 32>>(1 << 12)} {}
|
||||||
|
|
||||||
|
} // namespace Host1x
|
||||||
|
|
||||||
|
} // namespace Tegra
|
|
@ -6,7 +6,13 @@
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
|
#include "common/address_space.h"
|
||||||
#include "video_core/host1x/syncpoint_manager.h"
|
#include "video_core/host1x/syncpoint_manager.h"
|
||||||
|
#include "video_core/memory_manager.h"
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
class System;
|
||||||
|
} // namespace Core
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
||||||
|
@ -14,7 +20,7 @@ namespace Host1x {
|
||||||
|
|
||||||
class Host1x {
|
class Host1x {
|
||||||
public:
|
public:
|
||||||
Host1x() : syncpoint_manager{} {}
|
Host1x(Core::System& system);
|
||||||
|
|
||||||
SyncpointManager& GetSyncpointManager() {
|
SyncpointManager& GetSyncpointManager() {
|
||||||
return syncpoint_manager;
|
return syncpoint_manager;
|
||||||
|
@ -24,8 +30,27 @@ public:
|
||||||
return syncpoint_manager;
|
return syncpoint_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Tegra::MemoryManager& MemoryManager() {
|
||||||
|
return memory_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tegra::MemoryManager& MemoryManager() const {
|
||||||
|
return memory_manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
Common::FlatAllocator<u32, 0, 32>& Allocator() {
|
||||||
|
return *allocator;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Common::FlatAllocator<u32, 0, 32>& Allocator() const {
|
||||||
|
return *allocator;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Core::System& system;
|
||||||
SyncpointManager syncpoint_manager;
|
SyncpointManager syncpoint_manager;
|
||||||
|
Tegra::MemoryManager memory_manager;
|
||||||
|
std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Host1x
|
} // namespace Host1x
|
||||||
|
|
|
@ -2,7 +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 "video_core/gpu.h"
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/host1x/nvdec.h"
|
#include "video_core/host1x/nvdec.h"
|
||||||
|
|
||||||
namespace Tegra::Host1x {
|
namespace Tegra::Host1x {
|
||||||
|
@ -10,7 +10,8 @@ namespace Tegra::Host1x {
|
||||||
#define NVDEC_REG_INDEX(field_name) \
|
#define NVDEC_REG_INDEX(field_name) \
|
||||||
(offsetof(NvdecCommon::NvdecRegisters, field_name) / sizeof(u64))
|
(offsetof(NvdecCommon::NvdecRegisters, field_name) / sizeof(u64))
|
||||||
|
|
||||||
Nvdec::Nvdec(GPU& gpu_) : gpu(gpu_), state{}, codec(std::make_unique<Codec>(gpu, state)) {}
|
Nvdec::Nvdec(Host1x& host1x_)
|
||||||
|
: host1x(host1x_), state{}, codec(std::make_unique<Codec>(host1x, state)) {}
|
||||||
|
|
||||||
Nvdec::~Nvdec() = default;
|
Nvdec::~Nvdec() = default;
|
||||||
|
|
||||||
|
|
|
@ -9,13 +9,14 @@
|
||||||
#include "video_core/host1x/codecs/codec.h"
|
#include "video_core/host1x/codecs/codec.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
|
||||||
namespace Host1x {
|
namespace Host1x {
|
||||||
|
|
||||||
|
class Host1x;
|
||||||
|
|
||||||
class Nvdec {
|
class Nvdec {
|
||||||
public:
|
public:
|
||||||
explicit Nvdec(GPU& gpu);
|
explicit Nvdec(Host1x& host1x);
|
||||||
~Nvdec();
|
~Nvdec();
|
||||||
|
|
||||||
/// Writes the method into the state, Invoke Execute() if encountered
|
/// Writes the method into the state, Invoke Execute() if encountered
|
||||||
|
@ -28,7 +29,7 @@ private:
|
||||||
/// Invoke codec to decode a frame
|
/// Invoke codec to decode a frame
|
||||||
void Execute();
|
void Execute();
|
||||||
|
|
||||||
GPU& gpu;
|
Host1x& host1x;
|
||||||
NvdecCommon::NvdecRegisters state;
|
NvdecCommon::NvdecRegisters state;
|
||||||
std::unique_ptr<Codec> codec;
|
std::unique_ptr<Codec> codec;
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,14 +3,13 @@
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "sync_manager.h"
|
#include "sync_manager.h"
|
||||||
#include "video_core/gpu.h"
|
|
||||||
#include "video_core/host1x/host1x.h"
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/host1x/syncpoint_manager.h"
|
#include "video_core/host1x/syncpoint_manager.h"
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
namespace Host1x {
|
namespace Host1x {
|
||||||
|
|
||||||
SyncptIncrManager::SyncptIncrManager(GPU& gpu_) : gpu(gpu_) {}
|
SyncptIncrManager::SyncptIncrManager(Host1x& host1x_) : host1x(host1x_) {}
|
||||||
SyncptIncrManager::~SyncptIncrManager() = default;
|
SyncptIncrManager::~SyncptIncrManager() = default;
|
||||||
|
|
||||||
void SyncptIncrManager::Increment(u32 id) {
|
void SyncptIncrManager::Increment(u32 id) {
|
||||||
|
@ -40,7 +39,7 @@ void SyncptIncrManager::IncrementAllDone() {
|
||||||
if (!increments[done_count].complete) {
|
if (!increments[done_count].complete) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
auto& syncpoint_manager = gpu.Host1x().GetSyncpointManager();
|
auto& syncpoint_manager = host1x.GetSyncpointManager();
|
||||||
syncpoint_manager.IncrementGuest(increments[done_count].syncpt_id);
|
syncpoint_manager.IncrementGuest(increments[done_count].syncpt_id);
|
||||||
syncpoint_manager.IncrementHost(increments[done_count].syncpt_id);
|
syncpoint_manager.IncrementHost(increments[done_count].syncpt_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,10 +9,10 @@
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
|
|
||||||
class GPU;
|
|
||||||
|
|
||||||
namespace Host1x {
|
namespace Host1x {
|
||||||
|
|
||||||
|
class Host1x;
|
||||||
|
|
||||||
struct SyncptIncr {
|
struct SyncptIncr {
|
||||||
u32 id;
|
u32 id;
|
||||||
u32 class_id;
|
u32 class_id;
|
||||||
|
@ -25,7 +25,7 @@ struct SyncptIncr {
|
||||||
|
|
||||||
class SyncptIncrManager {
|
class SyncptIncrManager {
|
||||||
public:
|
public:
|
||||||
explicit SyncptIncrManager(GPU& gpu);
|
explicit SyncptIncrManager(Host1x& host1x);
|
||||||
~SyncptIncrManager();
|
~SyncptIncrManager();
|
||||||
|
|
||||||
/// Add syncpoint id and increment all
|
/// Add syncpoint id and increment all
|
||||||
|
@ -45,7 +45,7 @@ private:
|
||||||
std::mutex increment_lock;
|
std::mutex increment_lock;
|
||||||
u32 current_id{};
|
u32 current_id{};
|
||||||
|
|
||||||
GPU& gpu;
|
Host1x& host1x;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Host1x
|
} // namespace Host1x
|
||||||
|
|
|
@ -19,7 +19,7 @@ extern "C" {
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
|
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
#include "video_core/gpu.h"
|
#include "video_core/host1x/host1x.h"
|
||||||
#include "video_core/host1x/nvdec.h"
|
#include "video_core/host1x/nvdec.h"
|
||||||
#include "video_core/host1x/vic.h"
|
#include "video_core/host1x/vic.h"
|
||||||
#include "video_core/memory_manager.h"
|
#include "video_core/memory_manager.h"
|
||||||
|
@ -49,8 +49,8 @@ union VicConfig {
|
||||||
BitField<46, 14, u64_le> surface_height_minus1;
|
BitField<46, 14, u64_le> surface_height_minus1;
|
||||||
};
|
};
|
||||||
|
|
||||||
Vic::Vic(GPU& gpu_, std::shared_ptr<Nvdec> nvdec_processor_)
|
Vic::Vic(Host1x& host1x_, std::shared_ptr<Nvdec> nvdec_processor_)
|
||||||
: gpu(gpu_),
|
: host1x(host1x_),
|
||||||
nvdec_processor(std::move(nvdec_processor_)), converted_frame_buffer{nullptr, av_free} {}
|
nvdec_processor(std::move(nvdec_processor_)), converted_frame_buffer{nullptr, av_free} {}
|
||||||
|
|
||||||
Vic::~Vic() = default;
|
Vic::~Vic() = default;
|
||||||
|
@ -81,7 +81,7 @@ void Vic::Execute() {
|
||||||
LOG_ERROR(Service_NVDRV, "VIC Luma address not set.");
|
LOG_ERROR(Service_NVDRV, "VIC Luma address not set.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const VicConfig config{gpu.MemoryManager().Read<u64>(config_struct_address + 0x20)};
|
const VicConfig config{host1x.MemoryManager().Read<u64>(config_struct_address + 0x20)};
|
||||||
const AVFramePtr frame_ptr = nvdec_processor->GetFrame();
|
const AVFramePtr frame_ptr = nvdec_processor->GetFrame();
|
||||||
const auto* frame = frame_ptr.get();
|
const auto* frame = frame_ptr.get();
|
||||||
if (!frame) {
|
if (!frame) {
|
||||||
|
@ -159,12 +159,12 @@ void Vic::WriteRGBFrame(const AVFrame* frame, const VicConfig& config) {
|
||||||
Texture::SwizzleSubrect(width, height, width * 4, width, 4, luma_buffer.data(),
|
Texture::SwizzleSubrect(width, height, width * 4, width, 4, luma_buffer.data(),
|
||||||
converted_frame_buf_addr, block_height, 0, 0);
|
converted_frame_buf_addr, block_height, 0, 0);
|
||||||
|
|
||||||
gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
|
host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
|
||||||
} else {
|
} else {
|
||||||
// send pitch linear frame
|
// send pitch linear frame
|
||||||
const size_t linear_size = width * height * 4;
|
const size_t linear_size = width * height * 4;
|
||||||
gpu.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr,
|
host1x.MemoryManager().WriteBlock(output_surface_luma_address, converted_frame_buf_addr,
|
||||||
linear_size);
|
linear_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,8 +192,8 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
|
||||||
luma_buffer[dst + x] = luma_src[src + x];
|
luma_buffer[dst + x] = luma_src[src + x];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(),
|
host1x.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(),
|
||||||
luma_buffer.size());
|
luma_buffer.size());
|
||||||
|
|
||||||
// Chroma
|
// Chroma
|
||||||
const std::size_t half_height = frame_height / 2;
|
const std::size_t half_height = frame_height / 2;
|
||||||
|
@ -234,8 +234,8 @@ void Vic::WriteYUVFrame(const AVFrame* frame, const VicConfig& config) {
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gpu.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(),
|
host1x.MemoryManager().WriteBlock(output_surface_chroma_address, chroma_buffer.data(),
|
||||||
chroma_buffer.size());
|
chroma_buffer.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Host1x
|
} // namespace Host1x
|
||||||
|
|
|
@ -10,10 +10,10 @@
|
||||||
struct SwsContext;
|
struct SwsContext;
|
||||||
|
|
||||||
namespace Tegra {
|
namespace Tegra {
|
||||||
class GPU;
|
|
||||||
|
|
||||||
namespace Host1x {
|
namespace Host1x {
|
||||||
|
|
||||||
|
class Host1x;
|
||||||
class Nvdec;
|
class Nvdec;
|
||||||
union VicConfig;
|
union VicConfig;
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ public:
|
||||||
SetOutputSurfaceChromaUnusedOffset = 0x1ca
|
SetOutputSurfaceChromaUnusedOffset = 0x1ca
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit Vic(GPU& gpu, std::shared_ptr<Nvdec> nvdec_processor);
|
explicit Vic(Host1x& host1x, std::shared_ptr<Nvdec> nvdec_processor);
|
||||||
|
|
||||||
~Vic();
|
~Vic();
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ private:
|
||||||
|
|
||||||
void WriteYUVFrame(const AVFrame* frame, const VicConfig& config);
|
void WriteYUVFrame(const AVFrame* frame, const VicConfig& config);
|
||||||
|
|
||||||
GPU& gpu;
|
Host1x& host1x;
|
||||||
std::shared_ptr<Tegra::Host1x::Nvdec> nvdec_processor;
|
std::shared_ptr<Tegra::Host1x::Nvdec> nvdec_processor;
|
||||||
|
|
||||||
/// Avoid reallocation of the following buffers every frame, as their
|
/// Avoid reallocation of the following buffers every frame, as their
|
||||||
|
|
Loading…
Reference in New Issue