Compare commits

..

1 Commits

Author SHA1 Message Date
Liam
e797a917a9 kernel: implement transfer memory 2023-10-04 22:32:27 -04:00
15 changed files with 162 additions and 38 deletions

View File

@@ -2949,6 +2949,23 @@ Result KPageTable::UnlockForIpcUserBuffer(KProcessAddress address, size_t size)
KMemoryAttribute::Locked, nullptr));
}
Result KPageTable::LockForTransferMemory(KPageGroup* out, KProcessAddress address, size_t size,
KMemoryPermission perm) {
R_RETURN(this->LockMemoryAndOpen(out, nullptr, address, size, KMemoryState::FlagCanTransfer,
KMemoryState::FlagCanTransfer, KMemoryPermission::All,
KMemoryPermission::UserReadWrite, KMemoryAttribute::All,
KMemoryAttribute::None, perm, KMemoryAttribute::Locked));
}
Result KPageTable::UnlockForTransferMemory(KProcessAddress address, size_t size,
const KPageGroup& pg) {
R_RETURN(this->UnlockMemory(address, size, KMemoryState::FlagCanTransfer,
KMemoryState::FlagCanTransfer, KMemoryPermission::None,
KMemoryPermission::None, KMemoryAttribute::All,
KMemoryAttribute::Locked, KMemoryPermission::UserReadWrite,
KMemoryAttribute::Locked, std::addressof(pg)));
}
Result KPageTable::LockForCodeMemory(KPageGroup* out, KProcessAddress addr, size_t size) {
R_RETURN(this->LockMemoryAndOpen(
out, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, KMemoryState::FlagCanCodeMemory,

View File

@@ -104,6 +104,9 @@ public:
Result CleanupForIpcServer(KProcessAddress address, size_t size, KMemoryState dst_state);
Result CleanupForIpcClient(KProcessAddress address, size_t size, KMemoryState dst_state);
Result LockForTransferMemory(KPageGroup* out, KProcessAddress address, size_t size,
KMemoryPermission perm);
Result UnlockForTransferMemory(KProcessAddress address, size_t size, const KPageGroup& pg);
Result LockForCodeMemory(KPageGroup* out, KProcessAddress addr, size_t size);
Result UnlockForCodeMemory(KProcessAddress addr, size_t size, const KPageGroup& pg);
Result MakeAndOpenPageGroup(KPageGroup* out, KProcessAddress address, size_t num_pages,

View File

@@ -1,6 +1,7 @@
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/scope_exit.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_transfer_memory.h"
@@ -9,28 +10,50 @@
namespace Kernel {
KTransferMemory::KTransferMemory(KernelCore& kernel)
: KAutoObjectWithSlabHeapAndContainer{kernel} {}
: KAutoObjectWithSlabHeapAndContainer{kernel}, m_lock{kernel} {}
KTransferMemory::~KTransferMemory() = default;
Result KTransferMemory::Initialize(KProcessAddress address, std::size_t size,
Svc::MemoryPermission owner_perm) {
Result KTransferMemory::Initialize(KProcessAddress addr, std::size_t size,
Svc::MemoryPermission own_perm) {
// Set members.
m_owner = GetCurrentProcessPointer(m_kernel);
// TODO(bunnei): Lock for transfer memory
// Get the owner page table.
auto& page_table = m_owner->GetPageTable();
// Construct the page group, guarding to make sure our state is valid on exit.
m_page_group.emplace(m_kernel, page_table.GetBlockInfoManager());
auto pg_guard = SCOPE_GUARD({ m_page_group.reset(); });
// Lock the memory.
R_TRY(page_table.LockForTransferMemory(std::addressof(*m_page_group), addr, size,
ConvertToKMemoryPermission(own_perm)));
// Set remaining tracking members.
m_owner->Open();
m_owner_perm = owner_perm;
m_address = address;
m_size = size;
m_owner_perm = own_perm;
m_address = addr;
m_is_initialized = true;
m_is_mapped = false;
// We succeeded.
pg_guard.Cancel();
R_SUCCEED();
}
void KTransferMemory::Finalize() {}
void KTransferMemory::Finalize() {
// Unlock.
if (!m_is_mapped) {
const size_t size = m_page_group->GetNumPages() * PageSize;
ASSERT(R_SUCCEEDED(
m_owner->GetPageTable().UnlockForTransferMemory(m_address, size, *m_page_group)));
}
// Close the page group.
m_page_group->Close();
m_page_group->Finalize();
}
void KTransferMemory::PostDestroy(uintptr_t arg) {
KProcess* owner = reinterpret_cast<KProcess*>(arg);
@@ -38,4 +61,54 @@ void KTransferMemory::PostDestroy(uintptr_t arg) {
owner->Close();
}
Result KTransferMemory::Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm) {
// Validate the size.
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
// Validate the permission.
R_UNLESS(m_owner_perm == map_perm, ResultInvalidState);
// Lock ourselves.
KScopedLightLock lk(m_lock);
// Ensure we're not already mapped.
R_UNLESS(!m_is_mapped, ResultInvalidState);
// Map the memory.
const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None)
? KMemoryState::Transfered
: KMemoryState::SharedTransfered;
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().MapPageGroup(
address, *m_page_group, state, KMemoryPermission::UserReadWrite));
// Mark ourselves as mapped.
m_is_mapped = true;
R_SUCCEED();
}
Result KTransferMemory::Unmap(KProcessAddress address, size_t size) {
// Validate the size.
R_UNLESS(m_page_group->GetNumPages() == Common::DivideUp(size, PageSize), ResultInvalidSize);
// Lock ourselves.
KScopedLightLock lk(m_lock);
// Unmap the memory.
const KMemoryState state = (m_owner_perm == Svc::MemoryPermission::None)
? KMemoryState::Transfered
: KMemoryState::SharedTransfered;
R_TRY(GetCurrentProcess(m_kernel).GetPageTable().UnmapPageGroup(address, *m_page_group, state));
// Mark ourselves as unmapped.
ASSERT(m_is_mapped);
m_is_mapped = false;
R_SUCCEED();
}
size_t KTransferMemory::GetSize() const {
return m_is_initialized ? m_page_group->GetNumPages() * PageSize : 0;
}
} // namespace Kernel

View File

@@ -3,6 +3,9 @@
#pragma once
#include <optional>
#include "core/hle/kernel/k_page_group.h"
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
@@ -48,16 +51,19 @@ public:
return m_address;
}
size_t GetSize() const {
return m_is_initialized ? m_size : 0;
}
size_t GetSize() const;
Result Map(KProcessAddress address, size_t size, Svc::MemoryPermission map_perm);
Result Unmap(KProcessAddress address, size_t size);
private:
std::optional<KPageGroup> m_page_group{};
KProcess* m_owner{};
KProcessAddress m_address{};
KLightLock m_lock;
Svc::MemoryPermission m_owner_perm{};
size_t m_size{};
bool m_is_initialized{};
bool m_is_mapped{};
};
} // namespace Kernel

View File

@@ -71,15 +71,59 @@ Result CreateTransferMemory(Core::System& system, Handle* out, u64 address, u64
}
Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size,
MemoryPermission owner_perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
MemoryPermission map_perm) {
// Validate the address/size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Validate the permission.
R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidState);
// Get the transfer memory.
KScopedAutoObject trmem = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KTransferMemory>(trmem_handle);
R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle);
// Verify that the mapping is in range.
R_UNLESS(GetCurrentProcess(system.Kernel())
.GetPageTable()
.CanContain(address, size, KMemoryState::Transfered),
ResultInvalidMemoryRegion);
// Map the transfer memory.
R_TRY(trmem->Map(address, size, map_perm));
// We succeeded.
R_SUCCEED();
}
Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
// Validate the address/size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Get the transfer memory.
KScopedAutoObject trmem = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KTransferMemory>(trmem_handle);
R_UNLESS(trmem.IsNotNull(), ResultInvalidHandle);
// Verify that the mapping is in range.
R_UNLESS(GetCurrentProcess(system.Kernel())
.GetPageTable()
.CanContain(address, size, KMemoryState::Transfered),
ResultInvalidMemoryRegion);
// Unmap the transfer memory.
R_TRY(trmem->Unmap(address, size));
R_SUCCEED();
}
Result MapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address,

View File

@@ -116,7 +116,6 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB
{GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV}, // E5B9G9R9_FLOAT
{GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT}, // D32_FLOAT
{GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT}, // D16_UNORM
{GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT_24_8}, // X8_D24_UNORM
{GL_STENCIL_INDEX8, GL_STENCIL, GL_UNSIGNED_BYTE}, // S8_UINT
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // D24_UNORM_S8_UINT
{GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, // S8_UINT_D24_UNORM

View File

@@ -214,9 +214,8 @@ struct FormatTuple {
{VK_FORMAT_E5B9G9R9_UFLOAT_PACK32}, // E5B9G9R9_FLOAT
// Depth formats
{VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT
{VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM
{VK_FORMAT_X8_D24_UNORM_PACK32, Attachable}, // X8_D24_UNORM
{VK_FORMAT_D32_SFLOAT, Attachable}, // D32_FLOAT
{VK_FORMAT_D16_UNORM, Attachable}, // D16_UNORM
// Stencil formats
{VK_FORMAT_S8_UINT, Attachable}, // S8_UINT

View File

@@ -96,7 +96,6 @@ std::size_t GetSizeInBytes(const Tegra::FramebufferConfig& framebuffer) {
VkFormat GetFormat(const Tegra::FramebufferConfig& framebuffer) {
switch (framebuffer.pixel_format) {
case Service::android::PixelFormat::Rgba8888:
case Service::android::PixelFormat::Rgbx8888:
return VK_FORMAT_A8B8G8R8_UNORM_PACK32;
case Service::android::PixelFormat::Rgb565:
return VK_FORMAT_R5G6B5_UNORM_PACK16;

View File

@@ -238,7 +238,6 @@ constexpr VkBorderColor ConvertBorderColor(const std::array<float, 4>& color) {
return any_r ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT;
case PixelFormat::D16_UNORM:
case PixelFormat::D32_FLOAT:
case PixelFormat::X8_D24_UNORM:
return VK_IMAGE_ASPECT_DEPTH_BIT;
case PixelFormat::S8_UINT:
return VK_IMAGE_ASPECT_STENCIL_BIT;

View File

@@ -85,8 +85,6 @@ PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
return PixelFormat::S8_UINT;
case Tegra::DepthFormat::Z32_FLOAT_X24S8_UINT:
return PixelFormat::D32_FLOAT_S8_UINT;
case Tegra::DepthFormat::X8Z24_UNORM:
return PixelFormat::X8_D24_UNORM;
default:
UNIMPLEMENTED_MSG("Unimplemented format={}", format);
return PixelFormat::S8_UINT_D24_UNORM;
@@ -204,7 +202,6 @@ PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format)
PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format) {
switch (format) {
case Service::android::PixelFormat::Rgba8888:
case Service::android::PixelFormat::Rgbx8888:
return PixelFormat::A8B8G8R8_UNORM;
case Service::android::PixelFormat::Rgb565:
return PixelFormat::R5G6B5_UNORM;

View File

@@ -115,7 +115,6 @@ enum class PixelFormat {
// Depth formats
D32_FLOAT = MaxColorFormat,
D16_UNORM,
X8_D24_UNORM,
MaxDepthFormat,
@@ -252,7 +251,6 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_WIDTH_TABLE = {{
1, // E5B9G9R9_FLOAT
1, // D32_FLOAT
1, // D16_UNORM
1, // X8_D24_UNORM
1, // S8_UINT
1, // D24_UNORM_S8_UINT
1, // S8_UINT_D24_UNORM
@@ -362,7 +360,6 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_HEIGHT_TABLE = {{
1, // E5B9G9R9_FLOAT
1, // D32_FLOAT
1, // D16_UNORM
1, // X8_D24_UNORM
1, // S8_UINT
1, // D24_UNORM_S8_UINT
1, // S8_UINT_D24_UNORM
@@ -472,7 +469,6 @@ constexpr std::array<u8, MaxPixelFormat> BITS_PER_BLOCK_TABLE = {{
32, // E5B9G9R9_FLOAT
32, // D32_FLOAT
16, // D16_UNORM
32, // X8_D24_UNORM
8, // S8_UINT
32, // D24_UNORM_S8_UINT
32, // S8_UINT_D24_UNORM

View File

@@ -142,10 +142,6 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red,
return PixelFormat::D16_UNORM;
case Hash(TextureFormat::Z16, UNORM, UINT, UINT, UINT, LINEAR):
return PixelFormat::D16_UNORM;
case Hash(TextureFormat::X8Z24, UNORM):
return PixelFormat::X8_D24_UNORM;
case Hash(TextureFormat::X8Z24, UNORM, UINT, UINT, UINT, LINEAR):
return PixelFormat::X8_D24_UNORM;
case Hash(TextureFormat::Z24S8, UINT, UNORM, UNORM, UNORM, LINEAR):
return PixelFormat::S8_UINT_D24_UNORM;
case Hash(TextureFormat::Z24S8, UINT, UNORM, UINT, UINT, LINEAR):

View File

@@ -211,8 +211,6 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str
return "D32_FLOAT";
case PixelFormat::D16_UNORM:
return "D16_UNORM";
case PixelFormat::X8_D24_UNORM:
return "X8_D24_UNORM";
case PixelFormat::S8_UINT:
return "S8_UINT";
case PixelFormat::D24_UNORM_S8_UINT:

View File

@@ -85,7 +85,6 @@ bool ImageViewBase::SupportsAnisotropy() const noexcept {
// Depth formats
case PixelFormat::D32_FLOAT:
case PixelFormat::D16_UNORM:
case PixelFormat::X8_D24_UNORM:
// Stencil formats
case PixelFormat::S8_UINT:
// DepthStencil formats

View File

@@ -200,7 +200,6 @@ std::unordered_map<VkFormat, VkFormatProperties> GetFormatProperties(vk::Physica
VK_FORMAT_BC7_UNORM_BLOCK,
VK_FORMAT_D16_UNORM,
VK_FORMAT_D16_UNORM_S8_UINT,
VK_FORMAT_X8_D24_UNORM_PACK32,
VK_FORMAT_D24_UNORM_S8_UINT,
VK_FORMAT_D32_SFLOAT,
VK_FORMAT_D32_SFLOAT_S8_UINT,