mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-09-03 16:15:44 +00:00
Fix metal renderer compilation
This commit is contained in:
parent
cb2ba129e8
commit
964b5632d1
6 changed files with 153 additions and 151 deletions
|
@ -1,27 +1,42 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "kernel_types.hpp"
|
|
||||||
|
#include "helpers.hpp"
|
||||||
|
|
||||||
class Memory;
|
class Memory;
|
||||||
|
|
||||||
|
enum class FcramRegion {
|
||||||
|
App = 0x100,
|
||||||
|
Sys = 0x200,
|
||||||
|
Base = 0x300,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct FcramBlock {
|
||||||
|
u32 paddr;
|
||||||
|
s32 pages;
|
||||||
|
|
||||||
|
FcramBlock(u32 paddr, s32 pages) : paddr(paddr), pages(pages) {}
|
||||||
|
};
|
||||||
|
|
||||||
using FcramBlockList = std::list<FcramBlock>;
|
using FcramBlockList = std::list<FcramBlock>;
|
||||||
|
|
||||||
class KFcram {
|
class KFcram {
|
||||||
struct Region {
|
struct Region {
|
||||||
struct Block {
|
struct Block {
|
||||||
s32 pages;
|
s32 pages;
|
||||||
s32 pageOffs;
|
s32 pageOffset;
|
||||||
bool used;
|
bool used;
|
||||||
|
|
||||||
Block(s32 pages, u32 pageOffs) : pages(pages), pageOffs(pageOffs), used(false) {}
|
Block(s32 pages, u32 pageOffset) : pages(pages), pageOffset(pageOffset), used(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::list<Block> blocks;
|
std::list<Block> blocks;
|
||||||
u32 start;
|
u32 start;
|
||||||
s32 pages;
|
s32 pages;
|
||||||
s32 freePages;
|
s32 freePages;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
Region() : start(0), pages(0) {}
|
Region() : start(0), pages(0) {}
|
||||||
void reset(u32 start, size_t size);
|
void reset(u32 start, size_t size);
|
||||||
void alloc(std::list<FcramBlock>& out, s32 pages, bool linear);
|
void alloc(std::list<FcramBlock>& out, s32 pages, bool linear);
|
||||||
|
@ -35,7 +50,8 @@ class KFcram {
|
||||||
Region appRegion, sysRegion, baseRegion;
|
Region appRegion, sysRegion, baseRegion;
|
||||||
uint8_t* fcram;
|
uint8_t* fcram;
|
||||||
std::unique_ptr<u32> refs;
|
std::unique_ptr<u32> refs;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
KFcram(Memory& memory);
|
KFcram(Memory& memory);
|
||||||
void reset(size_t ramSize, size_t appSize, size_t sysSize, size_t baseSize);
|
void reset(size_t ramSize, size_t appSize, size_t sysSize, size_t baseSize);
|
||||||
void alloc(FcramBlockList& out, s32 pages, FcramRegion region, bool linear);
|
void alloc(FcramBlockList& out, s32 pages, FcramRegion region, bool linear);
|
||||||
|
|
|
@ -1,99 +1,97 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "fs/archive_base.hpp"
|
#include "fs/archive_base.hpp"
|
||||||
#include "handles.hpp"
|
#include "handles.hpp"
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
#include "result/result.hpp"
|
#include "result/result.hpp"
|
||||||
|
|
||||||
enum class KernelObjectType : u8 {
|
enum class KernelObjectType : u8 {
|
||||||
AddressArbiter, Archive, Directory, File, MemoryBlock, Process, ResourceLimit, Session, Dummy,
|
AddressArbiter,
|
||||||
// Bundle waitable objects together in the enum to let the compiler optimize certain checks better
|
Archive,
|
||||||
Event, Mutex, Port, Semaphore, Timer, Thread
|
Directory,
|
||||||
|
File,
|
||||||
|
MemoryBlock,
|
||||||
|
Process,
|
||||||
|
ResourceLimit,
|
||||||
|
Session,
|
||||||
|
Dummy,
|
||||||
|
// Bundle waitable objects together in the enum to let the compiler optimize certain checks better
|
||||||
|
Event,
|
||||||
|
Mutex,
|
||||||
|
Port,
|
||||||
|
Semaphore,
|
||||||
|
Timer,
|
||||||
|
Thread
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ResourceLimitCategory : int {
|
enum class ResourceLimitCategory : int { Application = 0, SystemApplet = 1, LibraryApplet = 2, Misc = 3 };
|
||||||
Application = 0,
|
|
||||||
SystemApplet = 1,
|
|
||||||
LibraryApplet = 2,
|
|
||||||
Misc = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
// Reset types (for use with events and timers)
|
// Reset types (for use with events and timers)
|
||||||
enum class ResetType {
|
enum class ResetType {
|
||||||
OneShot = 0, // When the primitive is signaled, it will wake up exactly one thread and will clear itself automatically.
|
OneShot = 0, // When the primitive is signaled, it will wake up exactly one thread and will clear itself automatically.
|
||||||
Sticky = 1, // When the primitive is signaled, it will wake up all threads and it won't clear itself automatically.
|
Sticky = 1, // When the primitive is signaled, it will wake up all threads and it won't clear itself automatically.
|
||||||
Pulse = 2, // Only meaningful for timers: same as ONESHOT but it will periodically signal the timer instead of just once.
|
Pulse = 2, // Only meaningful for timers: same as ONESHOT but it will periodically signal the timer instead of just once.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ArbitrationType {
|
enum class ArbitrationType { Signal = 0, WaitIfLess = 1, DecrementAndWaitIfLess = 2, WaitIfLessTimeout = 3, DecrementAndWaitIfLessTimeout = 4 };
|
||||||
Signal = 0,
|
|
||||||
WaitIfLess = 1,
|
|
||||||
DecrementAndWaitIfLess = 2,
|
|
||||||
WaitIfLessTimeout = 3,
|
|
||||||
DecrementAndWaitIfLessTimeout = 4
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ProcessorID : s32 {
|
enum class ProcessorID : s32 {
|
||||||
AllCPUs = -1,
|
AllCPUs = -1,
|
||||||
Default = -2,
|
Default = -2,
|
||||||
|
|
||||||
AppCore = 0,
|
|
||||||
Syscore = 1,
|
|
||||||
New3DSExtra1 = 2,
|
|
||||||
New3DSExtra2 = 3
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class FcramRegion {
|
AppCore = 0,
|
||||||
App = 0x100,
|
Syscore = 1,
|
||||||
Sys = 0x200,
|
New3DSExtra1 = 2,
|
||||||
Base = 0x300
|
New3DSExtra2 = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AddressArbiter {};
|
struct AddressArbiter {};
|
||||||
|
|
||||||
struct ResourceLimits {
|
struct ResourceLimits {
|
||||||
HorizonHandle handle;
|
HorizonHandle handle;
|
||||||
|
|
||||||
s32 currentCommit = 0;
|
s32 currentCommit = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Process {
|
struct Process {
|
||||||
// Resource limits for this process
|
// Resource limits for this process
|
||||||
ResourceLimits limits;
|
ResourceLimits limits;
|
||||||
// Process ID
|
// Process ID
|
||||||
u32 id;
|
u32 id;
|
||||||
|
|
||||||
Process(u32 id) : id(id) {}
|
Process(u32 id) : id(id) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Event {
|
struct Event {
|
||||||
// Some events (for now, only the DSP semaphore events) need to execute a callback when signalled
|
// Some events (for now, only the DSP semaphore events) need to execute a callback when signalled
|
||||||
// This enum stores what kind of callback they should execute
|
// This enum stores what kind of callback they should execute
|
||||||
enum class CallbackType : u32 {
|
enum class CallbackType : u32 {
|
||||||
None, DSPSemaphore,
|
None,
|
||||||
};
|
DSPSemaphore,
|
||||||
|
};
|
||||||
|
|
||||||
u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
|
u64 waitlist; // A bitfield where each bit symbolizes if the thread with thread with the corresponding index is waiting on the event
|
||||||
ResetType resetType = ResetType::OneShot;
|
ResetType resetType = ResetType::OneShot;
|
||||||
CallbackType callback = CallbackType::None;
|
CallbackType callback = CallbackType::None;
|
||||||
bool fired = false;
|
bool fired = false;
|
||||||
|
|
||||||
Event(ResetType resetType) : resetType(resetType), waitlist(0) {}
|
Event(ResetType resetType) : resetType(resetType), waitlist(0) {}
|
||||||
Event(ResetType resetType, CallbackType cb) : resetType(resetType), waitlist(0), callback(cb) {}
|
Event(ResetType resetType, CallbackType cb) : resetType(resetType), waitlist(0), callback(cb) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Port {
|
struct Port {
|
||||||
static constexpr u32 maxNameLen = 11;
|
static constexpr u32 maxNameLen = 11;
|
||||||
|
|
||||||
char name[maxNameLen + 1] = {};
|
char name[maxNameLen + 1] = {};
|
||||||
bool isPublic = false; // Setting name=NULL creates a private port not accessible from svcConnectToPort.
|
bool isPublic = false; // Setting name=NULL creates a private port not accessible from svcConnectToPort.
|
||||||
|
|
||||||
Port(const char* name) {
|
Port(const char* name) {
|
||||||
// If the name is empty (ie the first char is the null terminator) then the port is private
|
// If the name is empty (ie the first char is the null terminator) then the port is private
|
||||||
isPublic = name[0] != '\0';
|
isPublic = name[0] != '\0';
|
||||||
std::strncpy(this->name, name, maxNameLen);
|
std::strncpy(this->name, name, maxNameLen);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Session {
|
struct Session {
|
||||||
|
@ -151,92 +149,90 @@ struct Thread {
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* kernelObjectTypeToString(KernelObjectType t) {
|
static const char* kernelObjectTypeToString(KernelObjectType t) {
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case KernelObjectType::AddressArbiter: return "address arbiter";
|
case KernelObjectType::AddressArbiter: return "address arbiter";
|
||||||
case KernelObjectType::Archive: return "archive";
|
case KernelObjectType::Archive: return "archive";
|
||||||
case KernelObjectType::Directory: return "directory";
|
case KernelObjectType::Directory: return "directory";
|
||||||
case KernelObjectType::Event: return "event";
|
case KernelObjectType::Event: return "event";
|
||||||
case KernelObjectType::File: return "file";
|
case KernelObjectType::File: return "file";
|
||||||
case KernelObjectType::MemoryBlock: return "memory block";
|
case KernelObjectType::MemoryBlock: return "memory block";
|
||||||
case KernelObjectType::Port: return "port";
|
case KernelObjectType::Port: return "port";
|
||||||
case KernelObjectType::Process: return "process";
|
case KernelObjectType::Process: return "process";
|
||||||
case KernelObjectType::ResourceLimit: return "resource limit";
|
case KernelObjectType::ResourceLimit: return "resource limit";
|
||||||
case KernelObjectType::Session: return "session";
|
case KernelObjectType::Session: return "session";
|
||||||
case KernelObjectType::Mutex: return "mutex";
|
case KernelObjectType::Mutex: return "mutex";
|
||||||
case KernelObjectType::Semaphore: return "semaphore";
|
case KernelObjectType::Semaphore: return "semaphore";
|
||||||
case KernelObjectType::Thread: return "thread";
|
case KernelObjectType::Thread: return "thread";
|
||||||
case KernelObjectType::Dummy: return "dummy";
|
case KernelObjectType::Dummy: return "dummy";
|
||||||
default: return "unknown";
|
default: return "unknown";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Mutex {
|
struct Mutex {
|
||||||
using Handle = HorizonHandle;
|
using Handle = HorizonHandle;
|
||||||
|
|
||||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||||
Handle ownerThread = 0; // Index of the thread that holds the mutex if it's locked
|
Handle ownerThread = 0; // Index of the thread that holds the mutex if it's locked
|
||||||
Handle handle; // Handle of the mutex itself
|
Handle handle; // Handle of the mutex itself
|
||||||
u32 lockCount; // Number of times this mutex has been locked by its daddy. 0 = not locked
|
u32 lockCount; // Number of times this mutex has been locked by its daddy. 0 = not locked
|
||||||
bool locked;
|
bool locked;
|
||||||
|
|
||||||
Mutex(bool lock, Handle handle) : locked(lock), waitlist(0), lockCount(lock ? 1 : 0), handle(handle) {}
|
Mutex(bool lock, Handle handle) : locked(lock), waitlist(0), lockCount(lock ? 1 : 0), handle(handle) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Semaphore {
|
struct Semaphore {
|
||||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||||
s32 availableCount;
|
s32 availableCount;
|
||||||
s32 maximumCount;
|
s32 maximumCount;
|
||||||
|
|
||||||
Semaphore(s32 initialCount, s32 maximumCount) : availableCount(initialCount), maximumCount(maximumCount), waitlist(0) {}
|
Semaphore(s32 initialCount, s32 maximumCount) : availableCount(initialCount), maximumCount(maximumCount), waitlist(0) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Timer {
|
struct Timer {
|
||||||
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
u64 waitlist; // Refer to the getWaitlist function below for documentation
|
||||||
ResetType resetType = ResetType::OneShot;
|
ResetType resetType = ResetType::OneShot;
|
||||||
|
|
||||||
u64 fireTick; // CPU tick the timer will be fired
|
u64 fireTick; // CPU tick the timer will be fired
|
||||||
u64 interval; // Number of ns until the timer fires for the second and future times
|
u64 interval; // Number of ns until the timer fires for the second and future times
|
||||||
bool fired; // Has this timer been signalled?
|
bool fired; // Has this timer been signalled?
|
||||||
bool running; // Is this timer running or stopped?
|
bool running; // Is this timer running or stopped?
|
||||||
|
|
||||||
Timer(ResetType type) : resetType(type), fireTick(0), interval(0), waitlist(0), fired(false), running(false) {}
|
Timer(ResetType type) : resetType(type), fireTick(0), interval(0), waitlist(0), fired(false), running(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MemoryBlock {
|
struct MemoryBlock {
|
||||||
u32 addr = 0;
|
u32 addr = 0;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
u32 myPermission = 0;
|
u32 myPermission = 0;
|
||||||
u32 otherPermission = 0;
|
u32 otherPermission = 0;
|
||||||
bool mapped = false;
|
bool mapped = false;
|
||||||
|
|
||||||
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm) : addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm),
|
MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm)
|
||||||
mapped(false) {}
|
: addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm), mapped(false) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generic kernel object class
|
// Generic kernel object class
|
||||||
struct KernelObject {
|
struct KernelObject {
|
||||||
using Handle = HorizonHandle;
|
using Handle = HorizonHandle;
|
||||||
|
|
||||||
Handle handle = 0; // A u32 the OS will use to identify objects
|
Handle handle = 0; // A u32 the OS will use to identify objects
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
KernelObjectType type;
|
KernelObjectType type;
|
||||||
|
|
||||||
KernelObject(Handle handle, KernelObjectType type) : handle(handle), type(type) {}
|
KernelObject(Handle handle, KernelObjectType type) : handle(handle), type(type) {}
|
||||||
|
|
||||||
// Our destructor does not free the data in order to avoid it being freed when our std::vector is expanded
|
// Our destructor does not free the data in order to avoid it being freed when our std::vector is expanded
|
||||||
// Thus, the kernel needs to delete it when appropriate
|
// Thus, the kernel needs to delete it when appropriate
|
||||||
~KernelObject() {}
|
~KernelObject() {}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* getData() {
|
T* getData() {
|
||||||
return static_cast<T*>(data);
|
return static_cast<T*>(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* getTypeName() const {
|
const char* getTypeName() const { return kernelObjectTypeToString(type); }
|
||||||
return kernelObjectTypeToString(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieves a reference to the waitlist for a specified object
|
// Retrieves a reference to the waitlist for a specified object
|
||||||
// We return a reference because this function is only called in the kernel threading internals
|
// We return a reference because this function is only called in the kernel threading internals
|
||||||
// We want the kernel to be able to easily manage waitlists, by reading/parsing them or setting/clearing bits.
|
// We want the kernel to be able to easily manage waitlists, by reading/parsing them or setting/clearing bits.
|
||||||
// As we mention in the definition of the "Event" struct, the format for wailists is very simple and made to be efficient.
|
// As we mention in the definition of the "Event" struct, the format for wailists is very simple and made to be efficient.
|
||||||
|
@ -252,15 +248,7 @@ struct KernelObject {
|
||||||
case KernelObjectType::Timer: return getData<Timer>()->waitlist;
|
case KernelObjectType::Timer: return getData<Timer>()->waitlist;
|
||||||
|
|
||||||
// This should be unreachable once we fully implement sync objects
|
// This should be unreachable once we fully implement sync objects
|
||||||
default: [[unlikely]]
|
default: [[unlikely]] Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
|
||||||
Helpers::panic("Called GetWaitList on kernel object without a waitlist (Type: %s)", getTypeName());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FcramBlock {
|
|
||||||
u32 paddr;
|
|
||||||
s32 pages;
|
|
||||||
|
|
||||||
FcramBlock(u32 paddr, s32 pages) : paddr(paddr), pages(pages) {}
|
|
||||||
};
|
|
|
@ -11,7 +11,7 @@
|
||||||
#include "handles.hpp"
|
#include "handles.hpp"
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
#include "host_memory/host_memory.h"
|
#include "host_memory/host_memory.h"
|
||||||
#include "kernel/kernel_types.hpp"
|
#include "kernel/fcram.hpp"
|
||||||
#include "loader/3dsx.hpp"
|
#include "loader/3dsx.hpp"
|
||||||
#include "loader/ncsd.hpp"
|
#include "loader/ncsd.hpp"
|
||||||
#include "result/result.hpp"
|
#include "result/result.hpp"
|
||||||
|
|
|
@ -14,10 +14,10 @@ namespace PICA {
|
||||||
|
|
||||||
bool needsSwizzle = false;
|
bool needsSwizzle = false;
|
||||||
MTL::TextureSwizzleChannels swizzle{
|
MTL::TextureSwizzleChannels swizzle{
|
||||||
.red = MTL::TextureSwizzleRed,
|
MTL::TextureSwizzleRed,
|
||||||
.green = MTL::TextureSwizzleGreen,
|
MTL::TextureSwizzleGreen,
|
||||||
.blue = MTL::TextureSwizzleBlue,
|
MTL::TextureSwizzleBlue,
|
||||||
.alpha = MTL::TextureSwizzleAlpha,
|
MTL::TextureSwizzleAlpha,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ namespace PICA {
|
||||||
case ColorFmt::RGBA5551: return MTL::PixelFormatRGBA8Unorm; // TODO: use MTL::PixelFormatBGR5A1Unorm?
|
case ColorFmt::RGBA5551: return MTL::PixelFormatRGBA8Unorm; // TODO: use MTL::PixelFormatBGR5A1Unorm?
|
||||||
case ColorFmt::RGB565: return MTL::PixelFormatRGBA8Unorm; // TODO: use MTL::PixelFormatB5G6R5Unorm?
|
case ColorFmt::RGB565: return MTL::PixelFormatRGBA8Unorm; // TODO: use MTL::PixelFormatB5G6R5Unorm?
|
||||||
#ifdef PANDA3DS_IOS
|
#ifdef PANDA3DS_IOS
|
||||||
case ColorFmt::RGBA4: return MTL::PixelFormatRGBA8Unorm; // IOS + Metal doesn't support AGBR4 properly, at least on simulator
|
case ColorFmt::RGBA4: return MTL::PixelFormatRGBA8Unorm; // IOS + Metal doesn't support AGBR4 properly, at least on simulator
|
||||||
#else
|
#else
|
||||||
case ColorFmt::RGBA4: return MTL::PixelFormatABGR4Unorm;
|
case ColorFmt::RGBA4: return MTL::PixelFormatABGR4Unorm;
|
||||||
#endif
|
#endif
|
||||||
|
@ -130,8 +130,7 @@ namespace PICA {
|
||||||
case PrimType::TriangleFan:
|
case PrimType::TriangleFan:
|
||||||
Helpers::warn("Triangle fans are not supported on Metal, using triangles instead");
|
Helpers::warn("Triangle fans are not supported on Metal, using triangles instead");
|
||||||
return MTL::PrimitiveTypeTriangle;
|
return MTL::PrimitiveTypeTriangle;
|
||||||
case PrimType::GeometryPrimitive:
|
case PrimType::GeometryPrimitive: return MTL::PrimitiveTypeTriangle;
|
||||||
return MTL::PrimitiveTypeTriangle;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
#include "memory.hpp"
|
#include "memory.hpp"
|
||||||
|
|
||||||
|
|
||||||
void KFcram::Region::reset(u32 start, size_t size) {
|
void KFcram::Region::reset(u32 start, size_t size) {
|
||||||
this->start = start;
|
this->start = start;
|
||||||
pages = size >> 12;
|
pages = size >> 12;
|
||||||
|
@ -22,7 +21,7 @@ void KFcram::Region::alloc(std::list<FcramBlock>& out, s32 allocPages, bool line
|
||||||
|
|
||||||
// If the current block is bigger than the allocation, split it
|
// If the current block is bigger than the allocation, split it
|
||||||
if (it->pages > allocPages) {
|
if (it->pages > allocPages) {
|
||||||
Block newBlock(it->pages - allocPages, it->pageOffs + allocPages);
|
Block newBlock(it->pages - allocPages, it->pageOffset + allocPages);
|
||||||
it->pages = allocPages;
|
it->pages = allocPages;
|
||||||
blocks.insert(it, newBlock);
|
blocks.insert(it, newBlock);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +31,7 @@ void KFcram::Region::alloc(std::list<FcramBlock>& out, s32 allocPages, bool line
|
||||||
allocPages -= it->pages;
|
allocPages -= it->pages;
|
||||||
freePages -= it->pages;
|
freePages -= it->pages;
|
||||||
|
|
||||||
u32 paddr = start + (it->pageOffs << 12);
|
u32 paddr = start + (it->pageOffset << 12);
|
||||||
FcramBlock outBlock(paddr, it->pages);
|
FcramBlock outBlock(paddr, it->pages);
|
||||||
out.push_back(outBlock);
|
out.push_back(outBlock);
|
||||||
|
|
||||||
|
|
|
@ -16,27 +16,27 @@ namespace PICA {
|
||||||
decodeTexelAI8ToRG8,
|
decodeTexelAI8ToRG8,
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
.red = MTL::TextureSwizzleRed,
|
MTL::TextureSwizzleRed,
|
||||||
.green = MTL::TextureSwizzleRed,
|
MTL::TextureSwizzleRed,
|
||||||
.blue = MTL::TextureSwizzleRed,
|
MTL::TextureSwizzleRed,
|
||||||
.alpha = MTL::TextureSwizzleGreen,
|
MTL::TextureSwizzleGreen,
|
||||||
}}, // IA8
|
}}, // IA8
|
||||||
{MTL::PixelFormatRG8Unorm, 2, decodeTexelGR8ToRG8}, // RG8
|
{MTL::PixelFormatRG8Unorm, 2, decodeTexelGR8ToRG8}, // RG8
|
||||||
{MTL::PixelFormatR8Unorm,
|
{MTL::PixelFormatR8Unorm,
|
||||||
1,
|
1,
|
||||||
decodeTexelI8ToR8,
|
decodeTexelI8ToR8,
|
||||||
true,
|
true,
|
||||||
{.red = MTL::TextureSwizzleRed, .green = MTL::TextureSwizzleRed, .blue = MTL::TextureSwizzleRed, .alpha = MTL::TextureSwizzleOne}}, // I8
|
{MTL::TextureSwizzleRed, MTL::TextureSwizzleRed, MTL::TextureSwizzleRed, MTL::TextureSwizzleOne}}, // I8
|
||||||
{MTL::PixelFormatA8Unorm, 1, decodeTexelA8ToA8}, // A8
|
{MTL::PixelFormatA8Unorm, 1, decodeTexelA8ToA8}, // A8
|
||||||
{MTL::PixelFormatABGR4Unorm, 2, decodeTexelAI4ToABGR4}, // IA4
|
{MTL::PixelFormatABGR4Unorm, 2, decodeTexelAI4ToABGR4}, // IA4
|
||||||
{MTL::PixelFormatR8Unorm,
|
{MTL::PixelFormatR8Unorm,
|
||||||
1,
|
1,
|
||||||
decodeTexelI4ToR8,
|
decodeTexelI4ToR8,
|
||||||
true,
|
true,
|
||||||
{.red = MTL::TextureSwizzleRed, .green = MTL::TextureSwizzleRed, .blue = MTL::TextureSwizzleRed, .alpha = MTL::TextureSwizzleOne}}, // I4
|
{MTL::TextureSwizzleRed, MTL::TextureSwizzleRed, MTL::TextureSwizzleRed, MTL::TextureSwizzleOne}}, // I4
|
||||||
{MTL::PixelFormatA8Unorm, 1, decodeTexelA4ToA8}, // A4
|
{MTL::PixelFormatA8Unorm, 1, decodeTexelA4ToA8}, // A4
|
||||||
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelETC1ToRGBA8}, // ETC1
|
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelETC1ToRGBA8}, // ETC1
|
||||||
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelETC1A4ToRGBA8}, // ETC1A4
|
{MTL::PixelFormatRGBA8Unorm, 4, decodeTexelETC1A4ToRGBA8}, // ETC1A4
|
||||||
};
|
};
|
||||||
|
|
||||||
void checkForMTLPixelFormatSupport(MTL::Device* device) {
|
void checkForMTLPixelFormatSupport(MTL::Device* device) {
|
||||||
|
@ -57,10 +57,10 @@ namespace PICA {
|
||||||
decodeTexelAI4ToRG8,
|
decodeTexelAI4ToRG8,
|
||||||
true,
|
true,
|
||||||
{
|
{
|
||||||
.red = MTL::TextureSwizzleRed,
|
MTL::TextureSwizzleRed,
|
||||||
.green = MTL::TextureSwizzleRed,
|
MTL::TextureSwizzleRed,
|
||||||
.blue = MTL::TextureSwizzleRed,
|
MTL::TextureSwizzleRed,
|
||||||
.alpha = MTL::TextureSwizzleGreen,
|
MTL::TextureSwizzleGreen,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue