Compare commits
29 Commits
__refs_pul
...
__refs_pul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
de18592179 | ||
|
|
c93ea96366 | ||
|
|
71b4a3b9f6 | ||
|
|
9dc0d13ba5 | ||
|
|
7222d9a4c3 | ||
|
|
9df8e924fb | ||
|
|
3ed8a1cac7 | ||
|
|
4a8eb6745e | ||
|
|
531c25386e | ||
|
|
174cba5c58 | ||
|
|
e59126809c | ||
|
|
1f6fe062ca | ||
|
|
ed542a7309 | ||
|
|
ef2d5ab0c1 | ||
|
|
59f4ff4659 | ||
|
|
5a28dce9eb | ||
|
|
8d4899d6ea | ||
|
|
95144cc39c | ||
|
|
8b4443c966 | ||
|
|
5ba71369ac | ||
|
|
5d529698c9 | ||
|
|
5b9bcbf438 | ||
|
|
2b082e2710 | ||
|
|
e52a87b98a | ||
|
|
0905dc1ff4 | ||
|
|
636ad34707 | ||
|
|
7fc516cc1a | ||
|
|
77bdc49343 | ||
|
|
1a1af3fda3 |
@@ -192,11 +192,6 @@ private:
|
||||
static_assert(position < 8 * sizeof(T), "Invalid position");
|
||||
static_assert(bits <= 8 * sizeof(T), "Invalid number of bits");
|
||||
static_assert(bits > 0, "Invalid number of bits");
|
||||
static_assert(std::is_pod<T>::value, "Invalid base type");
|
||||
static_assert(std::is_trivially_copyable_v<T>, "T must be trivially copyable in a BitField");
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
#if (__GNUC__ >= 5) || defined(__clang__) || defined(_MSC_VER)
|
||||
static_assert(std::is_trivially_copyable<BitField<0, 1, unsigned>>::value,
|
||||
"BitField must be trivially copyable");
|
||||
#endif
|
||||
|
||||
@@ -861,14 +861,14 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x2B, nullptr, "FlushDataCache"},
|
||||
{0x2C, nullptr, "MapPhysicalMemory"},
|
||||
{0x2D, nullptr, "UnmapPhysicalMemory"},
|
||||
{0x2E, nullptr, "Unknown"},
|
||||
{0x2E, nullptr, "GetNextThreadInfo"},
|
||||
{0x2F, nullptr, "GetLastThreadInfo"},
|
||||
{0x30, nullptr, "GetResourceLimitLimitValue"},
|
||||
{0x31, nullptr, "GetResourceLimitCurrentValue"},
|
||||
{0x32, SvcWrap<SetThreadActivity>, "SetThreadActivity"},
|
||||
{0x33, SvcWrap<GetThreadContext>, "GetThreadContext"},
|
||||
{0x34, nullptr, "Unknown"},
|
||||
{0x35, nullptr, "Unknown"},
|
||||
{0x34, nullptr, "WaitForAddress"},
|
||||
{0x35, nullptr, "SignalToAddress"},
|
||||
{0x36, nullptr, "Unknown"},
|
||||
{0x37, nullptr, "Unknown"},
|
||||
{0x38, nullptr, "Unknown"},
|
||||
@@ -876,7 +876,7 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x3A, nullptr, "Unknown"},
|
||||
{0x3B, nullptr, "Unknown"},
|
||||
{0x3C, nullptr, "DumpInfo"},
|
||||
{0x3D, nullptr, "Unknown"},
|
||||
{0x3D, nullptr, "DumpInfoNew"},
|
||||
{0x3E, nullptr, "Unknown"},
|
||||
{0x3F, nullptr, "Unknown"},
|
||||
{0x40, nullptr, "CreateSession"},
|
||||
@@ -887,9 +887,9 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x45, nullptr, "CreateEvent"},
|
||||
{0x46, nullptr, "Unknown"},
|
||||
{0x47, nullptr, "Unknown"},
|
||||
{0x48, nullptr, "Unknown"},
|
||||
{0x49, nullptr, "Unknown"},
|
||||
{0x4A, nullptr, "Unknown"},
|
||||
{0x48, nullptr, "AllocateUnsafeMemory"},
|
||||
{0x49, nullptr, "FreeUnsafeMemory"},
|
||||
{0x4A, nullptr, "SetUnsafeAllocationLimit"},
|
||||
{0x4B, nullptr, "CreateJitMemory"},
|
||||
{0x4C, nullptr, "MapJitMemory"},
|
||||
{0x4D, nullptr, "SleepSystem"},
|
||||
@@ -926,7 +926,7 @@ static const FunctionDef SVC_Table[] = {
|
||||
{0x6C, nullptr, "SetHardwareBreakPoint"},
|
||||
{0x6D, nullptr, "GetDebugThreadParam"},
|
||||
{0x6E, nullptr, "Unknown"},
|
||||
{0x6F, nullptr, "Unknown"},
|
||||
{0x6F, nullptr, "GetMemoryInfo"},
|
||||
{0x70, nullptr, "CreatePort"},
|
||||
{0x71, nullptr, "ManageNamedPort"},
|
||||
{0x72, nullptr, "ConnectToPort"},
|
||||
|
||||
@@ -38,7 +38,10 @@ class IProfile final : public ServiceFramework<IProfile> {
|
||||
public:
|
||||
IProfile() : ServiceFramework("IProfile") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "Get"},
|
||||
{1, &IProfile::GetBase, "GetBase"},
|
||||
{10, nullptr, "GetImageSize"},
|
||||
{11, nullptr, "LoadImage"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
@@ -59,6 +62,11 @@ public:
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IManagerForApplication::CheckAvailability, "CheckAvailability"},
|
||||
{1, &IManagerForApplication::GetAccountId, "GetAccountId"},
|
||||
{2, nullptr, "EnsureIdTokenCacheAsync"},
|
||||
{3, nullptr, "LoadIdTokenCache"},
|
||||
{130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"},
|
||||
{150, nullptr, "CreateAuthorizationRequest"},
|
||||
{160, nullptr, "StoreOpenContext"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/alignment.h"
|
||||
#include "common/microprofile.h"
|
||||
#include "common/scope_exit.h"
|
||||
#include "core/core.h"
|
||||
#include "core/core_timing.h"
|
||||
@@ -128,6 +129,8 @@ void NVFlinger::Compose() {
|
||||
// Search for a queued buffer and acquire it
|
||||
auto buffer = buffer_queue->AcquireBuffer();
|
||||
|
||||
MicroProfileFlip();
|
||||
|
||||
if (buffer == boost::none) {
|
||||
// There was no queued buffer to draw, render previous frame
|
||||
Core::System::GetInstance().perf_stats.EndGameFrame();
|
||||
|
||||
@@ -36,6 +36,7 @@ SET::SET() : ServiceFramework("set") {
|
||||
{5, nullptr, "GetAvailableLanguageCodes2"},
|
||||
{6, nullptr, "GetAvailableLanguageCodeCount2"},
|
||||
{7, nullptr, "GetKeyCodeMap"},
|
||||
{8, nullptr, "GetQuestFlag"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,15 @@ SET_CAL::SET_CAL() : ServiceFramework("set:cal") {
|
||||
{21, nullptr, "GetEticketDeviceKey"},
|
||||
{22, nullptr, "GetSpeakerParameter"},
|
||||
{23, nullptr, "GetLcdVendorId"},
|
||||
{24, nullptr, "GetEciDeviceCertificate2"},
|
||||
{25, nullptr, "GetEciDeviceKey2"},
|
||||
{26, nullptr, "GetAmiiboKey"},
|
||||
{27, nullptr, "GetAmiiboEcqvCertificate"},
|
||||
{28, nullptr, "GetAmiiboEcdsaCertificate"},
|
||||
{29, nullptr, "GetAmiiboEcqvBlsKey"},
|
||||
{30, nullptr, "GetAmiiboEcqvBlsCertificate"},
|
||||
{31, nullptr, "GetAmiiboEcqvBlsRootCertificate"},
|
||||
{32, nullptr, "GetUnknownId"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
||||
{2, nullptr, "GetNetworkSettings"},
|
||||
{3, nullptr, "GetFirmwareVersion"},
|
||||
{4, nullptr, "GetFirmwareVersion2"},
|
||||
{5, nullptr, "GetFirmwareVersionDigest"},
|
||||
{7, nullptr, "GetLockScreenFlag"},
|
||||
{8, nullptr, "SetLockScreenFlag"},
|
||||
{9, nullptr, "GetBacklightSettings"},
|
||||
@@ -159,6 +160,15 @@ SET_SYS::SET_SYS() : ServiceFramework("set:sys") {
|
||||
{138, nullptr, "GetWebInspectorFlag"},
|
||||
{139, nullptr, "GetAllowedSslHosts"},
|
||||
{140, nullptr, "GetHostFsMountPoint"},
|
||||
{141, nullptr, "GetRequiresRunRepairTimeReviser"},
|
||||
{142, nullptr, "SetRequiresRunRepairTimeReviser"},
|
||||
{143, nullptr, "SetBlePairingSettings"},
|
||||
{144, nullptr, "GetBlePairingSettings"},
|
||||
{145, nullptr, "GetConsoleSixAxisSensorAngularVelocityTimeBias"},
|
||||
{146, nullptr, "SetConsoleSixAxisSensorAngularVelocityTimeBias"},
|
||||
{147, nullptr, "GetConsoleSixAxisSensorAngularAcceleration"},
|
||||
{148, nullptr, "SetConsoleSixAxisSensorAngularAcceleration"},
|
||||
{149, nullptr, "GetRebootlessSystemUpdateVersion"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -79,9 +79,34 @@ BSD::BSD(const char* name) : ServiceFramework(name) {
|
||||
{0, &BSD::RegisterClient, "RegisterClient"},
|
||||
{1, &BSD::StartMonitoring, "StartMonitoring"},
|
||||
{2, &BSD::Socket, "Socket"},
|
||||
{3, nullptr, "SocketExempt"},
|
||||
{4, nullptr, "Open"},
|
||||
{5, nullptr, "Select"},
|
||||
{6, nullptr, "Poll"},
|
||||
{7, nullptr, "Sysctl"},
|
||||
{8, nullptr, "Recv"},
|
||||
{9, nullptr, "RecvFrom"},
|
||||
{10, nullptr, "Send"},
|
||||
{11, &BSD::SendTo, "SendTo"},
|
||||
{12, nullptr, "Accept"},
|
||||
{13, nullptr, "Bind"},
|
||||
{14, &BSD::Connect, "Connect"},
|
||||
{15, nullptr, "GetPeerName"},
|
||||
{16, nullptr, "GetSockName"},
|
||||
{17, nullptr, "GetSockOpt"},
|
||||
{18, nullptr, "Listen"},
|
||||
{19, nullptr, "Ioctl"},
|
||||
{20, nullptr, "Fcntl"},
|
||||
{21, nullptr, "SetSockOpt"},
|
||||
{22, nullptr, "Shutdown"},
|
||||
{23, nullptr, "ShutdownAllSockets"},
|
||||
{24, nullptr, "Write"},
|
||||
{25, nullptr, "Read"},
|
||||
{26, &BSD::Close, "Close"},
|
||||
{27, nullptr, "DuplicateSocket"},
|
||||
{28, nullptr, "GetResourceStatistics"},
|
||||
{29, nullptr, "RecvMMsg"},
|
||||
{30, nullptr, "SendMMsg"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ SFDNSRES::SFDNSRES() : ServiceFramework("sfdnsres") {
|
||||
{7, nullptr, "GetNameInfo"},
|
||||
{8, nullptr, "RequestCancelHandle"},
|
||||
{9, nullptr, "CancelSocketCall"},
|
||||
{11, nullptr, "ClearDnsIpServerAddressArray"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,12 @@ SPL::SPL(std::shared_ptr<Module> module) : Module::Interface(std::move(module),
|
||||
{23, nullptr, "GetSplWaitEvent"},
|
||||
{24, nullptr, "SetSharedData"},
|
||||
{25, nullptr, "GetSharedData"},
|
||||
{26, nullptr, "ImportSslRsaKey"},
|
||||
{27, nullptr, "SecureExpModWithSslKey"},
|
||||
{28, nullptr, "ImportEsRsaKey"},
|
||||
{29, nullptr, "SecureExpModWithEsKey"},
|
||||
{30, nullptr, "EncryptManuRsaKeyForImport"},
|
||||
{31, nullptr, "GetPackage2Hash"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,11 @@ public:
|
||||
ISystemClock() : ServiceFramework("ISystemClock") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &ISystemClock::GetCurrentTime, "GetCurrentTime"},
|
||||
{2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"}};
|
||||
{1, nullptr, "SetCurrentTime"},
|
||||
{2, &ISystemClock::GetSystemClockContext, "GetSystemClockContext"},
|
||||
{3, nullptr, "SetSystemClockContext"},
|
||||
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,17 @@ TIME_S::TIME_S(std::shared_ptr<Module> time) : Module::Interface(std::move(time)
|
||||
{2, &TIME_S::GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &TIME_S::GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &TIME_S::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
||||
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
||||
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, nullptr, "GetClockSnapshot"},
|
||||
{401, nullptr, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, nullptr, "CalculateSpanBetween"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,17 @@ TIME_U::TIME_U(std::shared_ptr<Module> time) : Module::Interface(std::move(time)
|
||||
{2, &TIME_U::GetStandardSteadyClock, "GetStandardSteadyClock"},
|
||||
{3, &TIME_U::GetTimeZoneService, "GetTimeZoneService"},
|
||||
{4, &TIME_U::GetStandardLocalSystemClock, "GetStandardLocalSystemClock"},
|
||||
{5, nullptr, "GetEphemeralNetworkSystemClock"},
|
||||
{50, nullptr, "SetStandardSteadyClockInternalOffset"},
|
||||
{100, nullptr, "IsStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{101, nullptr, "SetStandardUserSystemClockAutomaticCorrectionEnabled"},
|
||||
{102, nullptr, "GetStandardUserSystemClockInitialYear"},
|
||||
{200, nullptr, "IsStandardNetworkSystemClockAccuracySufficient"},
|
||||
{300, nullptr, "CalculateMonotonicSystemClockBaseTimePoint"},
|
||||
{400, nullptr, "GetClockSnapshot"},
|
||||
{401, nullptr, "GetClockSnapshotFromSystemClockContext"},
|
||||
{500, nullptr, "CalculateStandardUserSystemClockDifferenceByUser"},
|
||||
{501, nullptr, "CalculateSpanBetween"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -580,7 +580,48 @@ public:
|
||||
ISystemDisplayService() : ServiceFramework("ISystemDisplayService") {
|
||||
static const FunctionInfo functions[] = {
|
||||
{1200, nullptr, "GetZOrderCountMin"},
|
||||
{1202, nullptr, "GetZOrderCountMax"},
|
||||
{1203, nullptr, "GetDisplayLogicalResolution"},
|
||||
{1204, nullptr, "SetDisplayMagnification"},
|
||||
{2201, nullptr, "SetLayerPosition"},
|
||||
{2203, nullptr, "SetLayerSize"},
|
||||
{2204, nullptr, "GetLayerZ"},
|
||||
{2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"},
|
||||
{2207, nullptr, "SetLayerVisibility"},
|
||||
{2209, nullptr, "SetLayerAlpha"},
|
||||
{2312, nullptr, "CreateStrayLayer"},
|
||||
{2400, nullptr, "OpenIndirectLayer"},
|
||||
{2401, nullptr, "CloseIndirectLayer"},
|
||||
{2402, nullptr, "FlipIndirectLayer"},
|
||||
{3000, nullptr, "ListDisplayModes"},
|
||||
{3001, nullptr, "ListDisplayRgbRanges"},
|
||||
{3002, nullptr, "ListDisplayContentTypes"},
|
||||
{3200, nullptr, "GetDisplayMode"},
|
||||
{3201, nullptr, "SetDisplayMode"},
|
||||
{3202, nullptr, "GetDisplayUnderscan"},
|
||||
{3203, nullptr, "SetDisplayUnderscan"},
|
||||
{3204, nullptr, "GetDisplayContentType"},
|
||||
{3205, nullptr, "SetDisplayContentType"},
|
||||
{3206, nullptr, "GetDisplayRgbRange"},
|
||||
{3207, nullptr, "SetDisplayRgbRange"},
|
||||
{3208, nullptr, "GetDisplayCmuMode"},
|
||||
{3209, nullptr, "SetDisplayCmuMode"},
|
||||
{3210, nullptr, "GetDisplayContrastRatio"},
|
||||
{3211, nullptr, "SetDisplayContrastRatio"},
|
||||
{3214, nullptr, "GetDisplayGamma"},
|
||||
{3215, nullptr, "SetDisplayGamma"},
|
||||
{3216, nullptr, "GetDisplayCmuLuma"},
|
||||
{3217, nullptr, "SetDisplayCmuLuma"},
|
||||
{8225, nullptr, "GetSharedBufferMemoryHandleId"},
|
||||
{8250, nullptr, "OpenSharedLayer"},
|
||||
{8251, nullptr, "CloseSharedLayer"},
|
||||
{8252, nullptr, "ConnectSharedLayer"},
|
||||
{8253, nullptr, "DisconnectSharedLayer"},
|
||||
{8254, nullptr, "AcquireSharedFrameBuffer"},
|
||||
{8255, nullptr, "PresentSharedFrameBuffer"},
|
||||
{8256, nullptr, "GetSharedFrameBufferAcquirableEvent"},
|
||||
{8257, nullptr, "FillSharedFrameBufferColor"},
|
||||
{8258, nullptr, "CancelSharedFrameBuffer"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
@@ -603,10 +644,72 @@ public:
|
||||
explicit IManagerDisplayService(std::shared_ptr<NVFlinger::NVFlinger> nv_flinger)
|
||||
: ServiceFramework("IManagerDisplayService"), nv_flinger(std::move(nv_flinger)) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{200, nullptr, "AllocateProcessHeapBlock"},
|
||||
{201, nullptr, "FreeProcessHeapBlock"},
|
||||
{1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"},
|
||||
{1102, nullptr, "GetDisplayResolution"},
|
||||
{2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"},
|
||||
{2011, nullptr, "DestroyManagedLayer"},
|
||||
{2050, nullptr, "CreateIndirectLayer"},
|
||||
{2051, nullptr, "DestroyIndirectLayer"},
|
||||
{2052, nullptr, "CreateIndirectProducerEndPoint"},
|
||||
{2053, nullptr, "DestroyIndirectProducerEndPoint"},
|
||||
{2054, nullptr, "CreateIndirectConsumerEndPoint"},
|
||||
{2055, nullptr, "DestroyIndirectConsumerEndPoint"},
|
||||
{2300, nullptr, "AcquireLayerTexturePresentingEvent"},
|
||||
{2301, nullptr, "ReleaseLayerTexturePresentingEvent"},
|
||||
{2302, nullptr, "GetDisplayHotplugEvent"},
|
||||
{2402, nullptr, "GetDisplayHotplugState"},
|
||||
{2501, nullptr, "GetCompositorErrorInfo"},
|
||||
{2601, nullptr, "GetDisplayErrorEvent"},
|
||||
{4201, nullptr, "SetDisplayAlpha"},
|
||||
{4203, nullptr, "SetDisplayLayerStack"},
|
||||
{4205, nullptr, "SetDisplayPowerState"},
|
||||
{4206, nullptr, "SetDefaultDisplay"},
|
||||
{6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"},
|
||||
{6001, nullptr, "RemoveFromLayerStack"},
|
||||
{6002, nullptr, "SetLayerVisibility"},
|
||||
{6003, nullptr, "SetLayerConfig"},
|
||||
{6004, nullptr, "AttachLayerPresentationTracer"},
|
||||
{6005, nullptr, "DetachLayerPresentationTracer"},
|
||||
{6006, nullptr, "StartLayerPresentationRecording"},
|
||||
{6007, nullptr, "StopLayerPresentationRecording"},
|
||||
{6008, nullptr, "StartLayerPresentationFenceWait"},
|
||||
{6009, nullptr, "StopLayerPresentationFenceWait"},
|
||||
{6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"},
|
||||
{7000, nullptr, "SetContentVisibility"},
|
||||
{8000, nullptr, "SetConductorLayer"},
|
||||
{8100, nullptr, "SetIndirectProducerFlipOffset"},
|
||||
{8200, nullptr, "CreateSharedBufferStaticStorage"},
|
||||
{8201, nullptr, "CreateSharedBufferTransferMemory"},
|
||||
{8202, nullptr, "DestroySharedBuffer"},
|
||||
{8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"},
|
||||
{8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"},
|
||||
{8207, nullptr, "UnbindSharedLowLevelLayer"},
|
||||
{8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"},
|
||||
{8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"},
|
||||
{8210, nullptr, "CreateSharedLayer"},
|
||||
{8211, nullptr, "DestroySharedLayer"},
|
||||
{8216, nullptr, "AttachSharedLayerToLowLevelLayer"},
|
||||
{8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"},
|
||||
{8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"},
|
||||
{8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"},
|
||||
{8220, nullptr, "GetSharedLayerDetachReadyEvent"},
|
||||
{8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"},
|
||||
{8222, nullptr, "CheckSharedLowLevelLayerSynchronized"},
|
||||
{8223, nullptr, "RegisterSharedBufferImporterAruid"},
|
||||
{8224, nullptr, "UnregisterSharedBufferImporterAruid"},
|
||||
{8227, nullptr, "CreateSharedBufferProcessHeap"},
|
||||
{8228, nullptr, "GetSharedLayerLayerStacks"},
|
||||
{8229, nullptr, "SetSharedLayerLayerStacks"},
|
||||
{8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"},
|
||||
{8292, nullptr, "FillDetachedSharedFrameBufferColor"},
|
||||
{8293, nullptr, "GetDetachedSharedFrameBufferImage"},
|
||||
{8294, nullptr, "SetDetachedSharedFrameBufferImage"},
|
||||
{8295, nullptr, "CopyDetachedSharedFrameBufferImage"},
|
||||
{8296, nullptr, "SetDetachedSharedFrameBufferSubImage"},
|
||||
{8297, nullptr, "GetSharedFrameBufferContentParameter"},
|
||||
{8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
@@ -825,13 +928,21 @@ IApplicationDisplayService::IApplicationDisplayService(
|
||||
"GetIndirectDisplayTransactionService"},
|
||||
{1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"},
|
||||
{1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"},
|
||||
{1011, nullptr, "OpenDefaultDisplay"},
|
||||
{1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"},
|
||||
{1101, nullptr, "SetDisplayEnabled"},
|
||||
{1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"},
|
||||
{2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
|
||||
{2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"},
|
||||
{2021, nullptr, "CloseLayer"},
|
||||
{2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"},
|
||||
{2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"},
|
||||
{2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},
|
||||
{2102, nullptr, "ConvertScalingMode"},
|
||||
{2450, nullptr, "GetIndirectLayerImageMap"},
|
||||
{2451, nullptr, "GetIndirectLayerImageCropMap"},
|
||||
{2460, nullptr, "GetIndirectLayerImageRequiredMemoryInfo"},
|
||||
{5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"},
|
||||
{5203, nullptr, "GetDisplayVsyncEventForDebug"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ VI_U::VI_U(std::shared_ptr<Module> module, std::shared_ptr<NVFlinger::NVFlinger>
|
||||
: Module::Interface(std::move(module), "vi:u", std::move(nv_flinger)) {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &VI_U::GetDisplayService, "GetDisplayService"},
|
||||
{3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -74,8 +74,6 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
|
||||
|
||||
regs.reg_array[method] = value;
|
||||
|
||||
#define MAXWELL3D_REG_INDEX(field_name) (offsetof(Regs, field_name) / sizeof(u32))
|
||||
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(code_address.code_address_high):
|
||||
case MAXWELL3D_REG_INDEX(code_address.code_address_low): {
|
||||
@@ -136,7 +134,7 @@ void Maxwell3D::WriteReg(u32 method, u32 value, u32 remaining_params) {
|
||||
break;
|
||||
}
|
||||
|
||||
#undef MAXWELL3D_REG_INDEX
|
||||
VideoCore::g_renderer->Rasterizer()->NotifyMaxwellRegisterChanged(method);
|
||||
|
||||
if (debug_context) {
|
||||
debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr);
|
||||
@@ -165,6 +163,7 @@ void Maxwell3D::ProcessQueryGet() {
|
||||
void Maxwell3D::DrawArrays() {
|
||||
LOG_DEBUG(HW_GPU, "called, topology=%d, count=%d", regs.draw.topology.Value(),
|
||||
regs.vertex_buffer.count);
|
||||
ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
|
||||
|
||||
auto debug_context = Core::System::GetInstance().GetGPUDebugContext();
|
||||
|
||||
@@ -176,7 +175,8 @@ void Maxwell3D::DrawArrays() {
|
||||
debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr);
|
||||
}
|
||||
|
||||
VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(false /*is_indexed*/);
|
||||
const bool is_indexed{regs.index_array.count && !regs.vertex_buffer.count};
|
||||
VideoCore::g_renderer->Rasterizer()->AccelerateDrawBatch(is_indexed);
|
||||
}
|
||||
|
||||
void Maxwell3D::ProcessCBBind(Regs::ShaderStage stage) {
|
||||
@@ -221,7 +221,8 @@ Texture::TICEntry Maxwell3D::GetTICEntry(u32 tic_index) const {
|
||||
ASSERT_MSG(tic_entry.header_version == Texture::TICHeaderVersion::BlockLinear,
|
||||
"TIC versions other than BlockLinear are unimplemented");
|
||||
|
||||
ASSERT_MSG(tic_entry.texture_type == Texture::TextureType::Texture2D,
|
||||
ASSERT_MSG((tic_entry.texture_type == Texture::TextureType::Texture2D) ||
|
||||
(tic_entry.texture_type == Texture::TextureType::Texture2DNoMipmap),
|
||||
"Texture types other than Texture2D are unimplemented");
|
||||
|
||||
auto r_type = tic_entry.r_type.Value();
|
||||
|
||||
@@ -20,6 +20,9 @@
|
||||
namespace Tegra {
|
||||
namespace Engines {
|
||||
|
||||
#define MAXWELL3D_REG_INDEX(field_name) \
|
||||
(offsetof(Tegra::Engines::Maxwell3D::Regs, field_name) / sizeof(u32))
|
||||
|
||||
class Maxwell3D final {
|
||||
public:
|
||||
explicit Maxwell3D(MemoryManager& memory_manager);
|
||||
@@ -248,6 +251,52 @@ public:
|
||||
Patches = 0xe,
|
||||
};
|
||||
|
||||
enum class IndexFormat : u32 {
|
||||
UnsignedByte = 0x0,
|
||||
UnsignedShort = 0x1,
|
||||
UnsignedInt = 0x2,
|
||||
};
|
||||
|
||||
struct Blend {
|
||||
enum class Equation : u32 {
|
||||
Add = 1,
|
||||
Subtract = 2,
|
||||
ReverseSubtract = 3,
|
||||
Min = 4,
|
||||
Max = 5,
|
||||
};
|
||||
|
||||
enum class Factor : u32 {
|
||||
Zero = 0x1,
|
||||
One = 0x2,
|
||||
SourceColor = 0x3,
|
||||
OneMinusSourceColor = 0x4,
|
||||
SourceAlpha = 0x5,
|
||||
OneMinusSourceAlpha = 0x6,
|
||||
DestAlpha = 0x7,
|
||||
OneMinusDestAlpha = 0x8,
|
||||
DestColor = 0x9,
|
||||
OneMinusDestColor = 0xa,
|
||||
SourceAlphaSaturate = 0xb,
|
||||
Source1Color = 0x10,
|
||||
OneMinusSource1Color = 0x11,
|
||||
Source1Alpha = 0x12,
|
||||
OneMinusSource1Alpha = 0x13,
|
||||
ConstantColor = 0x61,
|
||||
OneMinusConstantColor = 0x62,
|
||||
ConstantAlpha = 0x63,
|
||||
OneMinusConstantAlpha = 0x64,
|
||||
};
|
||||
|
||||
u32 separate_alpha;
|
||||
Equation equation_rgb;
|
||||
Factor factor_source_rgb;
|
||||
Factor factor_dest_rgb;
|
||||
Equation equation_a;
|
||||
Factor factor_source_a;
|
||||
Factor factor_dest_a;
|
||||
};
|
||||
|
||||
union {
|
||||
struct {
|
||||
INSERT_PADDING_WORDS(0x200);
|
||||
@@ -375,7 +424,42 @@ public:
|
||||
};
|
||||
} draw;
|
||||
|
||||
INSERT_PADDING_WORDS(0x139);
|
||||
INSERT_PADDING_WORDS(0x6B);
|
||||
|
||||
struct {
|
||||
u32 start_addr_high;
|
||||
u32 start_addr_low;
|
||||
u32 end_addr_high;
|
||||
u32 end_addr_low;
|
||||
IndexFormat format;
|
||||
u32 first;
|
||||
u32 count;
|
||||
|
||||
unsigned FormatSizeInBytes() const {
|
||||
switch (format) {
|
||||
case IndexFormat::UnsignedByte:
|
||||
return 1;
|
||||
case IndexFormat::UnsignedShort:
|
||||
return 2;
|
||||
case IndexFormat::UnsignedInt:
|
||||
return 4;
|
||||
}
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
GPUVAddr StartAddress() const {
|
||||
return static_cast<GPUVAddr>(
|
||||
(static_cast<GPUVAddr>(start_addr_high) << 32) | start_addr_low);
|
||||
}
|
||||
|
||||
GPUVAddr EndAddress() const {
|
||||
return static_cast<GPUVAddr>((static_cast<GPUVAddr>(end_addr_high) << 32) |
|
||||
end_addr_low);
|
||||
}
|
||||
} index_array;
|
||||
|
||||
INSERT_PADDING_WORDS(0xC7);
|
||||
|
||||
struct {
|
||||
u32 query_address_high;
|
||||
u32 query_address_low;
|
||||
@@ -410,7 +494,9 @@ public:
|
||||
}
|
||||
} vertex_array[NumVertexArrays];
|
||||
|
||||
INSERT_PADDING_WORDS(0x40);
|
||||
Blend blend;
|
||||
|
||||
INSERT_PADDING_WORDS(0x39);
|
||||
|
||||
struct {
|
||||
u32 limit_high;
|
||||
@@ -572,8 +658,10 @@ ASSERT_REG_POSITION(tsc, 0x557);
|
||||
ASSERT_REG_POSITION(tic, 0x55D);
|
||||
ASSERT_REG_POSITION(code_address, 0x582);
|
||||
ASSERT_REG_POSITION(draw, 0x585);
|
||||
ASSERT_REG_POSITION(index_array, 0x5F2);
|
||||
ASSERT_REG_POSITION(query, 0x6C0);
|
||||
ASSERT_REG_POSITION(vertex_array[0], 0x700);
|
||||
ASSERT_REG_POSITION(blend, 0x780);
|
||||
ASSERT_REG_POSITION(vertex_array_limit[0], 0x7C0);
|
||||
ASSERT_REG_POSITION(shader_config[0], 0x800);
|
||||
ASSERT_REG_POSITION(const_buffer, 0x8E0);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "common/bit_field.h"
|
||||
@@ -12,14 +13,10 @@ namespace Tegra {
|
||||
namespace Shader {
|
||||
|
||||
struct Register {
|
||||
Register() = default;
|
||||
constexpr Register() = default;
|
||||
|
||||
constexpr Register(u64 value) : value(value) {}
|
||||
|
||||
constexpr u64 GetIndex() const {
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr operator u64() const {
|
||||
return value;
|
||||
}
|
||||
@@ -43,13 +40,13 @@ struct Register {
|
||||
}
|
||||
|
||||
private:
|
||||
u64 value;
|
||||
u64 value{};
|
||||
};
|
||||
|
||||
union Attribute {
|
||||
Attribute() = default;
|
||||
|
||||
constexpr Attribute(u64 value) : value(value) {}
|
||||
constexpr explicit Attribute(u64 value) : value(value) {}
|
||||
|
||||
enum class Index : u64 {
|
||||
Position = 7,
|
||||
@@ -68,7 +65,20 @@ union Attribute {
|
||||
} fmt28;
|
||||
|
||||
BitField<39, 8, u64> reg;
|
||||
u64 value;
|
||||
u64 value{};
|
||||
};
|
||||
|
||||
union Sampler {
|
||||
Sampler() = default;
|
||||
|
||||
constexpr explicit Sampler(u64 value) : value(value) {}
|
||||
|
||||
enum class Index : u64 {
|
||||
Sampler_0 = 8,
|
||||
};
|
||||
|
||||
BitField<36, 13, Index> index;
|
||||
u64 value{};
|
||||
};
|
||||
|
||||
union Uniform {
|
||||
@@ -238,7 +248,7 @@ union OpCode {
|
||||
BitField<55, 9, Id> op3;
|
||||
BitField<52, 12, Id> op4;
|
||||
BitField<51, 13, Id> op5;
|
||||
u64 value;
|
||||
u64 value{};
|
||||
};
|
||||
static_assert(sizeof(OpCode) == 0x8, "Incorrect structure size");
|
||||
|
||||
@@ -280,6 +290,7 @@ enum class SubOp : u64 {
|
||||
Lg2 = 0x3,
|
||||
Rcp = 0x4,
|
||||
Rsq = 0x5,
|
||||
Min = 0x8,
|
||||
};
|
||||
|
||||
union Instruction {
|
||||
@@ -295,15 +306,25 @@ union Instruction {
|
||||
BitField<20, 8, Register> gpr20;
|
||||
BitField<20, 7, SubOp> sub_op;
|
||||
BitField<28, 8, Register> gpr28;
|
||||
BitField<36, 13, u64> imm36;
|
||||
BitField<39, 8, Register> gpr39;
|
||||
|
||||
union {
|
||||
BitField<20, 19, u64> imm20;
|
||||
BitField<45, 1, u64> negate_b;
|
||||
BitField<46, 1, u64> abs_a;
|
||||
BitField<48, 1, u64> negate_a;
|
||||
BitField<49, 1, u64> abs_b;
|
||||
BitField<50, 1, u64> abs_d;
|
||||
BitField<56, 1, u64> negate_imm;
|
||||
|
||||
float GetImm20() const {
|
||||
float result{};
|
||||
u32 imm{static_cast<u32>(imm20)};
|
||||
imm <<= 12;
|
||||
imm |= negate_imm ? 0x80000000 : 0;
|
||||
std::memcpy(&result, &imm, sizeof(imm));
|
||||
return result;
|
||||
}
|
||||
} alu;
|
||||
|
||||
union {
|
||||
@@ -311,11 +332,13 @@ union Instruction {
|
||||
BitField<49, 1, u64> negate_c;
|
||||
} ffma;
|
||||
|
||||
BitField<61, 1, u64> is_b_imm;
|
||||
BitField<60, 1, u64> is_b_gpr;
|
||||
BitField<59, 1, u64> is_c_gpr;
|
||||
|
||||
Attribute attribute;
|
||||
Uniform uniform;
|
||||
Sampler sampler;
|
||||
|
||||
u64 hex;
|
||||
};
|
||||
|
||||
@@ -15,7 +15,10 @@ namespace Tegra {
|
||||
|
||||
enum class RenderTargetFormat : u32 {
|
||||
NONE = 0x0,
|
||||
RGBA16_FLOAT = 0xCA,
|
||||
RGB10_A2_UNORM = 0xD1,
|
||||
RGBA8_UNORM = 0xD5,
|
||||
RGBA8_SRGB = 0xD6,
|
||||
};
|
||||
|
||||
class DebugContext;
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
virtual void DrawArrays() = 0;
|
||||
|
||||
/// Notify rasterizer that the specified Maxwell register has been changed
|
||||
virtual void NotifyMaxwellRegisterChanged(u32 id) = 0;
|
||||
virtual void NotifyMaxwellRegisterChanged(u32 method) = 0;
|
||||
|
||||
/// Notify rasterizer that all caches should be flushed to Switch memory
|
||||
virtual void FlushAll() = 0;
|
||||
|
||||
@@ -97,7 +97,6 @@ RasterizerOpenGL::RasterizerOpenGL() {
|
||||
state.draw.vertex_buffer = stream_buffer->GetHandle();
|
||||
|
||||
shader_program_manager = std::make_unique<GLShader::ProgramManager>();
|
||||
|
||||
state.draw.shader_program = 0;
|
||||
state.draw.vertex_array = hw_vao.handle;
|
||||
state.Apply();
|
||||
@@ -128,17 +127,6 @@ RasterizerOpenGL::~RasterizerOpenGL() {
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::AnalyzeVertexArray(bool is_indexed) {
|
||||
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||
|
||||
if (is_indexed) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
// TODO(bunnei): Add support for 1+ vertex arrays
|
||||
vs_input_size = regs.vertex_buffer.count * regs.vertex_array[0].stride;
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
|
||||
MICROPROFILE_SCOPE(OpenGL_VAO);
|
||||
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||
@@ -150,6 +138,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
|
||||
|
||||
// TODO(bunnei): Add support for 1+ vertex arrays
|
||||
const auto& vertex_array{regs.vertex_array[0]};
|
||||
const auto& vertex_array_limit{regs.vertex_array_limit[0]};
|
||||
ASSERT_MSG(vertex_array.enable, "vertex array 0 is disabled?");
|
||||
ASSERT_MSG(!vertex_array.divisor, "vertex array 0 divisor is unimplemented!");
|
||||
for (unsigned index = 1; index < Maxwell::NumVertexArrays; ++index) {
|
||||
@@ -162,6 +151,10 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
|
||||
// to avoid OpenGL errors.
|
||||
for (unsigned index = 0; index < 16; ++index) {
|
||||
auto& attrib = regs.vertex_attrib_format[index];
|
||||
NGLOG_DEBUG(HW_GPU, "vertex attrib {}, count={}, size={}, type={}, offset={}, normalize={}",
|
||||
index, attrib.ComponentCount(), attrib.SizeString(), attrib.TypeString(),
|
||||
attrib.offset.Value(), attrib.IsNormalized());
|
||||
|
||||
glVertexAttribPointer(index, attrib.ComponentCount(), MaxwellToGL::VertexType(attrib),
|
||||
attrib.IsNormalized() ? GL_TRUE : GL_FALSE, vertex_array.stride,
|
||||
reinterpret_cast<GLvoid*>(buffer_offset + attrib.offset));
|
||||
@@ -170,7 +163,7 @@ void RasterizerOpenGL::SetupVertexArray(u8* array_ptr, GLintptr buffer_offset) {
|
||||
}
|
||||
|
||||
// Copy vertex array data
|
||||
const u32 data_size{vertex_array.stride * regs.vertex_buffer.count};
|
||||
const u64 data_size{vertex_array_limit.LimitAddress() - vertex_array.StartAddress() + 1};
|
||||
const VAddr data_addr{memory_manager->PhysicalToVirtualAddress(vertex_array.StartAddress())};
|
||||
res_cache.FlushRegion(data_addr, data_size, nullptr);
|
||||
Memory::ReadBlock(data_addr, array_ptr, data_size);
|
||||
@@ -333,13 +326,18 @@ void RasterizerOpenGL::DrawArrays() {
|
||||
|
||||
// Draw the vertex batch
|
||||
const bool is_indexed = accelerate_draw == AccelDraw::Indexed;
|
||||
AnalyzeVertexArray(is_indexed);
|
||||
const u64 index_buffer_size{regs.index_array.count * regs.index_array.FormatSizeInBytes()};
|
||||
const unsigned vertex_num{is_indexed ? regs.index_array.count : regs.vertex_buffer.count};
|
||||
|
||||
// TODO(bunnei): Add support for 1+ vertex arrays
|
||||
vs_input_size = vertex_num * regs.vertex_array[0].stride;
|
||||
|
||||
state.draw.vertex_buffer = stream_buffer->GetHandle();
|
||||
state.Apply();
|
||||
|
||||
size_t buffer_size = static_cast<size_t>(vs_input_size);
|
||||
if (is_indexed) {
|
||||
UNREACHABLE();
|
||||
buffer_size = Common::AlignUp(buffer_size, 4) + index_buffer_size;
|
||||
}
|
||||
|
||||
// Uniform space for the 5 shader stages
|
||||
@@ -354,9 +352,18 @@ void RasterizerOpenGL::DrawArrays() {
|
||||
SetupVertexArray(buffer_ptr, buffer_offset);
|
||||
ptr_pos += vs_input_size;
|
||||
|
||||
// If indexed mode, copy the index buffer
|
||||
GLintptr index_buffer_offset = 0;
|
||||
if (is_indexed) {
|
||||
UNREACHABLE();
|
||||
ptr_pos = Common::AlignUp(ptr_pos, 4);
|
||||
|
||||
const auto& memory_manager = Core::System().GetInstance().GPU().memory_manager;
|
||||
const VAddr index_data_addr{
|
||||
memory_manager->PhysicalToVirtualAddress(regs.index_array.StartAddress())};
|
||||
Memory::ReadBlock(index_data_addr, &buffer_ptr[ptr_pos], index_buffer_size);
|
||||
|
||||
index_buffer_offset = buffer_offset + static_cast<GLintptr>(ptr_pos);
|
||||
ptr_pos += index_buffer_size;
|
||||
}
|
||||
|
||||
SetupShaders(buffer_ptr, buffer_offset, ptr_pos);
|
||||
@@ -366,11 +373,16 @@ void RasterizerOpenGL::DrawArrays() {
|
||||
shader_program_manager->ApplyTo(state);
|
||||
state.Apply();
|
||||
|
||||
const GLenum primitive_mode{MaxwellToGL::PrimitiveTopology(regs.draw.topology)};
|
||||
if (is_indexed) {
|
||||
UNREACHABLE();
|
||||
const GLint index_min{static_cast<GLint>(regs.index_array.first)};
|
||||
const GLint index_max{static_cast<GLint>(regs.index_array.first + regs.index_array.count)};
|
||||
glDrawRangeElementsBaseVertex(primitive_mode, index_min, index_max, regs.index_array.count,
|
||||
MaxwellToGL::IndexFormat(regs.index_array.format),
|
||||
reinterpret_cast<const void*>(index_buffer_offset),
|
||||
-index_min);
|
||||
} else {
|
||||
glDrawArrays(MaxwellToGL::PrimitiveTopology(regs.draw.topology), 0,
|
||||
regs.vertex_buffer.count);
|
||||
glDrawArrays(primitive_mode, 0, regs.vertex_buffer.count);
|
||||
}
|
||||
|
||||
// Disable scissor test
|
||||
@@ -434,7 +446,32 @@ void RasterizerOpenGL::BindTextures() {
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 id) {}
|
||||
void RasterizerOpenGL::NotifyMaxwellRegisterChanged(u32 method) {
|
||||
const auto& regs = Core::System().GetInstance().GPU().Maxwell3D().regs;
|
||||
switch (method) {
|
||||
case MAXWELL3D_REG_INDEX(blend.separate_alpha):
|
||||
ASSERT_MSG(false, "unimplemented");
|
||||
break;
|
||||
case MAXWELL3D_REG_INDEX(blend.equation_rgb):
|
||||
state.blend.rgb_equation = MaxwellToGL::BlendEquation(regs.blend.equation_rgb);
|
||||
break;
|
||||
case MAXWELL3D_REG_INDEX(blend.factor_source_rgb):
|
||||
state.blend.src_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_rgb);
|
||||
break;
|
||||
case MAXWELL3D_REG_INDEX(blend.factor_dest_rgb):
|
||||
state.blend.dst_rgb_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_rgb);
|
||||
break;
|
||||
case MAXWELL3D_REG_INDEX(blend.equation_a):
|
||||
state.blend.a_equation = MaxwellToGL::BlendEquation(regs.blend.equation_a);
|
||||
break;
|
||||
case MAXWELL3D_REG_INDEX(blend.factor_source_a):
|
||||
state.blend.src_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_source_a);
|
||||
break;
|
||||
case MAXWELL3D_REG_INDEX(blend.factor_dest_a):
|
||||
state.blend.dst_a_func = MaxwellToGL::BlendFunc(regs.blend.factor_dest_a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void RasterizerOpenGL::FlushAll() {
|
||||
MICROPROFILE_SCOPE(OpenGL_CacheManagement);
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
~RasterizerOpenGL() override;
|
||||
|
||||
void DrawArrays() override;
|
||||
void NotifyMaxwellRegisterChanged(u32 id) override;
|
||||
void NotifyMaxwellRegisterChanged(u32 method) override;
|
||||
void FlushAll() override;
|
||||
void FlushRegion(VAddr addr, u64 size) override;
|
||||
void InvalidateRegion(VAddr addr, u64 size) override;
|
||||
@@ -155,7 +155,6 @@ private:
|
||||
|
||||
GLsizeiptr vs_input_size;
|
||||
|
||||
void AnalyzeVertexArray(bool is_indexed);
|
||||
void SetupVertexArray(u8* array_ptr, GLintptr buffer_offset);
|
||||
|
||||
std::array<OGLBuffer, Tegra::Engines::Maxwell3D::Regs::MaxShaderStage> uniform_buffers;
|
||||
|
||||
@@ -87,6 +87,7 @@ struct SurfaceParams {
|
||||
case Tegra::RenderTargetFormat::RGBA8_UNORM:
|
||||
return PixelFormat::RGBA8;
|
||||
default:
|
||||
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
@@ -96,6 +97,7 @@ struct SurfaceParams {
|
||||
case Tegra::FramebufferConfig::PixelFormat::ABGR8:
|
||||
return PixelFormat::RGBA8;
|
||||
default:
|
||||
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
@@ -108,6 +110,7 @@ struct SurfaceParams {
|
||||
case Tegra::Texture::TextureFormat::DXT1:
|
||||
return PixelFormat::DXT1;
|
||||
default:
|
||||
NGLOG_CRITICAL(HW_GPU, "Unimplemented format={}", static_cast<u32>(format));
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ using Tegra::Shader::Attribute;
|
||||
using Tegra::Shader::Instruction;
|
||||
using Tegra::Shader::OpCode;
|
||||
using Tegra::Shader::Register;
|
||||
using Tegra::Shader::Sampler;
|
||||
using Tegra::Shader::SubOp;
|
||||
using Tegra::Shader::Uniform;
|
||||
|
||||
@@ -155,23 +156,27 @@ private:
|
||||
|
||||
/// Generates code representing an input attribute register.
|
||||
std::string GetInputAttribute(Attribute::Index attribute) {
|
||||
declr_input_attribute.insert(attribute);
|
||||
switch (attribute) {
|
||||
case Attribute::Index::Position:
|
||||
return "position";
|
||||
default:
|
||||
const u32 index{static_cast<u32>(attribute) -
|
||||
static_cast<u32>(Attribute::Index::Attribute_0)};
|
||||
if (attribute >= Attribute::Index::Attribute_0) {
|
||||
declr_input_attribute.insert(attribute);
|
||||
return "input_attribute_" + std::to_string(index);
|
||||
}
|
||||
|
||||
const u32 index{static_cast<u32>(attribute) -
|
||||
static_cast<u32>(Attribute::Index::Attribute_0)};
|
||||
if (attribute >= Attribute::Index::Attribute_0) {
|
||||
return "input_attribute_" + std::to_string(index);
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled input attribute: {}", index);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled input attribute: 0x%02x", index);
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
/// Generates code representing an output attribute register.
|
||||
std::string GetOutputAttribute(Attribute::Index attribute) {
|
||||
switch (attribute) {
|
||||
case Attribute::Index::Position:
|
||||
return "gl_Position";
|
||||
return "position";
|
||||
default:
|
||||
const u32 index{static_cast<u32>(attribute) -
|
||||
static_cast<u32>(Attribute::Index::Attribute_0)};
|
||||
@@ -180,22 +185,42 @@ private:
|
||||
return "output_attribute_" + std::to_string(index);
|
||||
}
|
||||
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled output attribute: 0x%02x", index);
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled output attribute: {}", index);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates code representing an immediate value
|
||||
static std::string GetImmediate(const Instruction& instr) {
|
||||
return std::to_string(instr.alu.GetImm20());
|
||||
}
|
||||
|
||||
/// Generates code representing a temporary (GPR) register.
|
||||
std::string GetRegister(const Register& reg) {
|
||||
return *declr_register.insert("register_" + std::to_string(reg)).first;
|
||||
std::string GetRegister(const Register& reg, unsigned elem = 0) {
|
||||
if (stage == Maxwell3D::Regs::ShaderStage::Fragment && reg < 4) {
|
||||
// GPRs 0-3 are output color for the fragment shader
|
||||
return std::string{"color."} + "rgba"[(reg + elem) & 3];
|
||||
}
|
||||
|
||||
return *declr_register.insert("register_" + std::to_string(reg + elem)).first;
|
||||
}
|
||||
|
||||
/// Generates code representing a uniform (C buffer) register.
|
||||
std::string GetUniform(const Uniform& reg) {
|
||||
declr_const_buffers[reg.index].MarkAsUsed(reg.index, reg.offset, stage);
|
||||
declr_const_buffers[reg.index].MarkAsUsed(static_cast<unsigned>(reg.index),
|
||||
static_cast<unsigned>(reg.offset), stage);
|
||||
return 'c' + std::to_string(reg.index) + '[' + std::to_string(reg.offset) + ']';
|
||||
}
|
||||
|
||||
/// Generates code representing a texture sampler.
|
||||
std::string GetSampler(const Sampler& sampler) const {
|
||||
// TODO(Subv): Support more than just texture sampler 0
|
||||
ASSERT_MSG(sampler.index == Sampler::Index::Sampler_0, "unsupported");
|
||||
const unsigned index{static_cast<unsigned>(sampler.index.Value()) -
|
||||
static_cast<unsigned>(Sampler::Index::Sampler_0)};
|
||||
return "tex[" + std::to_string(index) + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds code that calls a subroutine.
|
||||
* @param subroutine the subroutine to call.
|
||||
@@ -217,12 +242,13 @@ private:
|
||||
* @param value the code representing the value to assign.
|
||||
*/
|
||||
void SetDest(u64 elem, const std::string& reg, const std::string& value,
|
||||
u64 dest_num_components, u64 value_num_components) {
|
||||
u64 dest_num_components, u64 value_num_components, bool is_abs = false) {
|
||||
std::string swizzle = ".";
|
||||
swizzle += "xyzw"[elem];
|
||||
|
||||
std::string dest = reg + (dest_num_components != 1 ? swizzle : "");
|
||||
std::string src = "(" + value + ")" + (value_num_components != 1 ? swizzle : "");
|
||||
src = is_abs ? "abs(" + src + ")" : src;
|
||||
|
||||
shader.AddLine(dest + " = " + src + ";");
|
||||
}
|
||||
@@ -240,8 +266,6 @@ private:
|
||||
|
||||
switch (OpCode::GetInfo(instr.opcode).type) {
|
||||
case OpCode::Type::Arithmetic: {
|
||||
ASSERT(!instr.alu.abs_d);
|
||||
|
||||
std::string dest = GetRegister(instr.gpr0);
|
||||
std::string op_a = instr.alu.negate_a ? "-" : "";
|
||||
op_a += GetRegister(instr.gpr8);
|
||||
@@ -250,63 +274,109 @@ private:
|
||||
}
|
||||
|
||||
std::string op_b = instr.alu.negate_b ? "-" : "";
|
||||
if (instr.is_b_gpr) {
|
||||
op_b += GetRegister(instr.gpr20);
|
||||
|
||||
if (instr.is_b_imm) {
|
||||
op_b += GetImmediate(instr);
|
||||
} else {
|
||||
op_b += GetUniform(instr.uniform);
|
||||
if (instr.is_b_gpr) {
|
||||
op_b += GetRegister(instr.gpr20);
|
||||
} else {
|
||||
op_b += GetUniform(instr.uniform);
|
||||
}
|
||||
}
|
||||
|
||||
if (instr.alu.abs_b) {
|
||||
op_b = "abs(" + op_b + ")";
|
||||
}
|
||||
|
||||
switch (instr.opcode.EffectiveOpCode()) {
|
||||
case OpCode::Id::FMUL_C:
|
||||
case OpCode::Id::FMUL_R: {
|
||||
SetDest(0, dest, op_a + " * " + op_b, 1, 1);
|
||||
case OpCode::Id::FMUL_R:
|
||||
case OpCode::Id::FMUL_IMM: {
|
||||
SetDest(0, dest, op_a + " * " + op_b, 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FADD_C:
|
||||
case OpCode::Id::FADD_R: {
|
||||
SetDest(0, dest, op_a + " + " + op_b, 1, 1);
|
||||
case OpCode::Id::FADD_R:
|
||||
case OpCode::Id::FADD_IMM: {
|
||||
SetDest(0, dest, op_a + " + " + op_b, 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::MUFU: {
|
||||
switch (instr.sub_op) {
|
||||
case SubOp::Cos:
|
||||
SetDest(0, dest, "cos(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Sin:
|
||||
SetDest(0, dest, "sin(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Ex2:
|
||||
SetDest(0, dest, "exp2(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Lg2:
|
||||
SetDest(0, dest, "log2(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Rcp:
|
||||
SetDest(0, dest, "1.0 / " + op_a, 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Rsq:
|
||||
SetDest(0, dest, "inversesqrt(" + op_a + ")", 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
case SubOp::Min:
|
||||
SetDest(0, dest, "min(" + op_a + "," + op_b + ")", 1, 1, instr.alu.abs_d);
|
||||
break;
|
||||
default:
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled MUFU sub op: {}",
|
||||
static_cast<unsigned>(instr.sub_op.Value()));
|
||||
UNREACHABLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: 0x%02x (%s): 0x%08x",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name.c_str(), instr.hex);
|
||||
throw DecompileFail("Unhandled instruction");
|
||||
break;
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled arithmetic instruction: {} ({}): {}",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name, instr.hex);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case OpCode::Type::Ffma: {
|
||||
ASSERT_MSG(!instr.ffma.negate_b, "untested");
|
||||
ASSERT_MSG(!instr.ffma.negate_c, "untested");
|
||||
|
||||
std::string dest = GetRegister(instr.gpr0);
|
||||
std::string op_a = GetRegister(instr.gpr8);
|
||||
|
||||
std::string op_b = instr.ffma.negate_b ? "-" : "";
|
||||
op_b += GetUniform(instr.uniform);
|
||||
|
||||
std::string op_c = instr.ffma.negate_c ? "-" : "";
|
||||
op_c += GetRegister(instr.gpr39);
|
||||
|
||||
switch (instr.opcode.EffectiveOpCode()) {
|
||||
case OpCode::Id::FFMA_CR: {
|
||||
SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1);
|
||||
op_b += GetUniform(instr.uniform);
|
||||
op_c += GetRegister(instr.gpr39);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FFMA_RR: {
|
||||
op_b += GetRegister(instr.gpr20);
|
||||
op_c += GetRegister(instr.gpr39);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FFMA_RC: {
|
||||
op_b += GetRegister(instr.gpr39);
|
||||
op_c += GetUniform(instr.uniform);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::FFMA_IMM: {
|
||||
op_b += GetImmediate(instr);
|
||||
op_c += GetRegister(instr.gpr39);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled FFMA instruction: {} ({}): {}",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name, instr.hex);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
default: {
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled arithmetic FFMA instruction: 0x%02x (%s): 0x%08x",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name.c_str(), instr.hex);
|
||||
throw DecompileFail("Unhandled instruction");
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetDest(0, dest, op_a + " * " + op_b + " + " + op_c, 1, 1);
|
||||
break;
|
||||
}
|
||||
case OpCode::Type::Memory: {
|
||||
@@ -315,22 +385,33 @@ private:
|
||||
|
||||
switch (instr.opcode.EffectiveOpCode()) {
|
||||
case OpCode::Id::LD_A: {
|
||||
ASSERT(instr.attribute.fmt20.size == 0);
|
||||
ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
|
||||
SetDest(instr.attribute.fmt20.element, gpr0, GetInputAttribute(attribute), 1, 4);
|
||||
break;
|
||||
}
|
||||
case OpCode::Id::ST_A: {
|
||||
ASSERT(instr.attribute.fmt20.size == 0);
|
||||
ASSERT_MSG(instr.attribute.fmt20.size == 0, "untested");
|
||||
SetDest(instr.attribute.fmt20.element, GetOutputAttribute(attribute), gpr0, 4, 1);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled memory instruction: 0x%02x (%s): 0x%08x",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name.c_str(), instr.hex);
|
||||
throw DecompileFail("Unhandled instruction");
|
||||
case OpCode::Id::TEXS: {
|
||||
ASSERT_MSG(instr.attribute.fmt20.size == 4, "untested");
|
||||
const std::string op_a = GetRegister(instr.gpr8);
|
||||
const std::string op_b = GetRegister(instr.gpr20);
|
||||
const std::string sampler = GetSampler(instr.sampler);
|
||||
const std::string coord = "vec2(" + op_a + ", " + op_b + ")";
|
||||
const std::string texture = "texture(" + sampler + ", " + coord + ")";
|
||||
for (unsigned elem = 0; elem < instr.attribute.fmt20.size; ++elem) {
|
||||
SetDest(elem, GetRegister(instr.gpr0, elem), texture, 1, 4);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled memory instruction: {} ({}): {}",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name, instr.hex);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -342,14 +423,18 @@ private:
|
||||
offset = PROGRAM_END - 1;
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
LOG_CRITICAL(HW_GPU, "Unhandled instruction: 0x%02x (%s): 0x%08x",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name.c_str(), instr.hex);
|
||||
throw DecompileFail("Unhandled instruction");
|
||||
case OpCode::Id::IPA: {
|
||||
const auto& attribute = instr.attribute.fmt28;
|
||||
std::string dest = GetRegister(instr.gpr0);
|
||||
SetDest(attribute.element, dest, GetInputAttribute(attribute.index), 1, 4);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
NGLOG_CRITICAL(HW_GPU, "Unhandled instruction: {} ({}): {}",
|
||||
static_cast<unsigned>(instr.opcode.EffectiveOpCode()),
|
||||
OpCode::GetInfo(instr.opcode).name, instr.hex);
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -514,7 +599,7 @@ boost::optional<ProgramResult> DecompileProgram(const ProgramCode& program_code,
|
||||
GLSLGenerator generator(subroutines, program_code, main_offset, stage);
|
||||
return ProgramResult{generator.GetShaderCode(), generator.GetEntries()};
|
||||
} catch (const DecompileFail& exception) {
|
||||
LOG_ERROR(HW_GPU, "Shader decompilation failed: %s", exception.what());
|
||||
NGLOG_ERROR(HW_GPU, "Shader decompilation failed: {}", exception.what());
|
||||
}
|
||||
return boost::none;
|
||||
}
|
||||
|
||||
@@ -27,10 +27,13 @@ out gl_PerVertex {
|
||||
vec4 gl_Position;
|
||||
};
|
||||
|
||||
out vec4 position;
|
||||
|
||||
void main() {
|
||||
exec_shader();
|
||||
}
|
||||
|
||||
gl_Position = position;
|
||||
}
|
||||
)";
|
||||
out += program.first;
|
||||
return {out, program.second};
|
||||
@@ -46,6 +49,7 @@ ProgramResult GenerateFragmentShader(const ShaderSetup& setup, const MaxwellFSCo
|
||||
.get_value_or({});
|
||||
out += R"(
|
||||
|
||||
in vec4 position;
|
||||
out vec4 color;
|
||||
|
||||
uniform sampler2D tex[32];
|
||||
|
||||
@@ -31,7 +31,7 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
|
||||
return GL_UNSIGNED_BYTE;
|
||||
}
|
||||
|
||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size=%s", attrib.SizeString().c_str());
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented vertex size={}", attrib.SizeString());
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
@@ -40,7 +40,21 @@ inline GLenum VertexType(Maxwell::VertexAttribute attrib) {
|
||||
return GL_FLOAT;
|
||||
}
|
||||
|
||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented vertex type=%s", attrib.TypeString().c_str());
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented vertex type={}", attrib.TypeString());
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
inline GLenum IndexFormat(Maxwell::IndexFormat index_format) {
|
||||
switch (index_format) {
|
||||
case Maxwell::IndexFormat::UnsignedByte:
|
||||
return GL_UNSIGNED_BYTE;
|
||||
case Maxwell::IndexFormat::UnsignedShort:
|
||||
return GL_UNSIGNED_SHORT;
|
||||
case Maxwell::IndexFormat::UnsignedInt:
|
||||
return GL_UNSIGNED_INT;
|
||||
}
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented index_format={}", static_cast<u32>(index_format));
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
@@ -52,7 +66,7 @@ inline GLenum PrimitiveTopology(Maxwell::PrimitiveTopology topology) {
|
||||
case Maxwell::PrimitiveTopology::TriangleStrip:
|
||||
return GL_TRIANGLE_STRIP;
|
||||
}
|
||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented primitive topology=%d", topology);
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented topology={}", static_cast<u32>(topology));
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
@@ -64,18 +78,90 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode) {
|
||||
case Tegra::Texture::TextureFilter::Nearest:
|
||||
return GL_NEAREST;
|
||||
}
|
||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode=%u",
|
||||
static_cast<u32>(filter_mode));
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented texture filter mode={}",
|
||||
static_cast<u32>(filter_mode));
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
inline GLenum WrapMode(Tegra::Texture::WrapMode wrap_mode) {
|
||||
switch (wrap_mode) {
|
||||
case Tegra::Texture::WrapMode::Wrap:
|
||||
return GL_REPEAT;
|
||||
case Tegra::Texture::WrapMode::ClampToEdge:
|
||||
return GL_CLAMP_TO_EDGE;
|
||||
case Tegra::Texture::WrapMode::ClampOGL:
|
||||
// TODO(Subv): GL_CLAMP was removed as of OpenGL 3.1, to implement GL_CLAMP, we can use
|
||||
// GL_CLAMP_TO_BORDER to get the border color of the texture, and then sample the edge to
|
||||
// manually mix them. However the shader part of this is not yet implemented.
|
||||
return GL_CLAMP_TO_BORDER;
|
||||
}
|
||||
LOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode=%u", static_cast<u32>(wrap_mode));
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented texture wrap mode={}",
|
||||
static_cast<u32>(wrap_mode));
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
inline GLenum BlendEquation(Maxwell::Blend::Equation equation) {
|
||||
switch (equation) {
|
||||
case Maxwell::Blend::Equation::Add:
|
||||
return GL_FUNC_ADD;
|
||||
case Maxwell::Blend::Equation::Subtract:
|
||||
return GL_FUNC_SUBTRACT;
|
||||
case Maxwell::Blend::Equation::ReverseSubtract:
|
||||
return GL_FUNC_REVERSE_SUBTRACT;
|
||||
case Maxwell::Blend::Equation::Min:
|
||||
return GL_MIN;
|
||||
case Maxwell::Blend::Equation::Max:
|
||||
return GL_MAX;
|
||||
}
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented blend equation={}", static_cast<u32>(equation));
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
||||
switch (factor) {
|
||||
case Maxwell::Blend::Factor::Zero:
|
||||
return GL_ZERO;
|
||||
case Maxwell::Blend::Factor::One:
|
||||
return GL_ONE;
|
||||
case Maxwell::Blend::Factor::SourceColor:
|
||||
return GL_SRC_COLOR;
|
||||
case Maxwell::Blend::Factor::OneMinusSourceColor:
|
||||
return GL_ONE_MINUS_SRC_COLOR;
|
||||
case Maxwell::Blend::Factor::SourceAlpha:
|
||||
return GL_SRC_ALPHA;
|
||||
case Maxwell::Blend::Factor::OneMinusSourceAlpha:
|
||||
return GL_ONE_MINUS_SRC_ALPHA;
|
||||
case Maxwell::Blend::Factor::DestAlpha:
|
||||
return GL_DST_ALPHA;
|
||||
case Maxwell::Blend::Factor::OneMinusDestAlpha:
|
||||
return GL_ONE_MINUS_DST_ALPHA;
|
||||
case Maxwell::Blend::Factor::DestColor:
|
||||
return GL_DST_COLOR;
|
||||
case Maxwell::Blend::Factor::OneMinusDestColor:
|
||||
return GL_ONE_MINUS_DST_COLOR;
|
||||
case Maxwell::Blend::Factor::SourceAlphaSaturate:
|
||||
return GL_SRC_ALPHA_SATURATE;
|
||||
case Maxwell::Blend::Factor::Source1Color:
|
||||
return GL_SRC1_COLOR;
|
||||
case Maxwell::Blend::Factor::OneMinusSource1Color:
|
||||
return GL_ONE_MINUS_SRC1_COLOR;
|
||||
case Maxwell::Blend::Factor::Source1Alpha:
|
||||
return GL_SRC1_ALPHA;
|
||||
case Maxwell::Blend::Factor::OneMinusSource1Alpha:
|
||||
return GL_ONE_MINUS_SRC1_ALPHA;
|
||||
case Maxwell::Blend::Factor::ConstantColor:
|
||||
return GL_CONSTANT_COLOR;
|
||||
case Maxwell::Blend::Factor::OneMinusConstantColor:
|
||||
return GL_ONE_MINUS_CONSTANT_COLOR;
|
||||
case Maxwell::Blend::Factor::ConstantAlpha:
|
||||
return GL_CONSTANT_ALPHA;
|
||||
case Maxwell::Blend::Factor::OneMinusConstantAlpha:
|
||||
return GL_ONE_MINUS_CONSTANT_ALPHA;
|
||||
}
|
||||
NGLOG_CRITICAL(Render_OpenGL, "Unimplemented blend factor={}", static_cast<u32>(factor));
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -13,8 +13,10 @@ namespace Tegra {
|
||||
namespace Texture {
|
||||
|
||||
enum class TextureFormat : u32 {
|
||||
A8R8G8B8 = 8,
|
||||
A8R8G8B8 = 0x8,
|
||||
DXT1 = 0x24,
|
||||
DXT23 = 0x25,
|
||||
DXT45 = 0x26,
|
||||
};
|
||||
|
||||
enum class TextureType : u32 {
|
||||
|
||||
Reference in New Issue
Block a user