Merge branch 'master' into TemporaryHackishBranch

This commit is contained in:
LunaMoo committed 2017-11-10 01:49:23 +01:00
commit 36a8b5b8c8
53 files changed
+1191 -1300

No files matched your search

+1 -1
View File
@@ -36,4 +36,4 @@ public:
void Resize() override {}
Draw::DrawContext *GetDrawContext() override { return nullptr; }
};
};
+4 -4
View File
@@ -399,7 +399,7 @@ void SetDefaultKeyMap(DefaultMaps dmap, bool replace) {
UpdateNativeMenuKeys();
}
const KeyMap_IntStrPair key_names[] = {
static const KeyMap_IntStrPair key_names[] = {
{NKCODE_A, "A"},
{NKCODE_B, "B"},
{NKCODE_C, "C"},
@@ -590,7 +590,7 @@ const KeyMap_IntStrPair key_names[] = {
{NKCODE_RIGHTBRACE, "}"},
};
const KeyMap_IntStrPair axis_names[] = {
static const KeyMap_IntStrPair axis_names[] = {
{JOYSTICK_AXIS_X, "X Axis"},
{JOYSTICK_AXIS_Y, "Y Axis"},
{JOYSTICK_AXIS_PRESSURE, "Pressure"},
@@ -878,7 +878,7 @@ void LoadFromIni(IniFile &file) {
IniFile::Section *controls = file.GetOrCreateSection("ControlMapping");
for (size_t i = 0; i < ARRAY_SIZE(psp_button_names); i++) {
std::string value;
controls->Get(psp_button_names[i].name.c_str(), &value, "");
controls->Get(psp_button_names[i].name, &value, "");
// Erase default mapping
g_controllerMap.erase(psp_button_names[i].key);
@@ -917,7 +917,7 @@ void SaveToIni(IniFile &file) {
value += ",";
}
controls->Set(psp_button_names[i].name.c_str(), value, "");
controls->Set(psp_button_names[i].name, value, "");
}
}
+1 -1
View File
@@ -86,7 +86,7 @@ namespace KeyMap {
// Key & Button names
struct KeyMap_IntStrPair {
int key;
std::string name;
const char *name;
};
// Use if you need to display the textual name
+64 -16
View File
@@ -8,6 +8,7 @@
#include "base/basictypes.h"
#include "VulkanContext.h"
#include "GPU/Common/ShaderCommon.h"
#include "Common/StringUtils.h"
#ifdef USE_CRT_DBG
#undef new
@@ -50,6 +51,20 @@ static const char *validationLayers[] = {
*/
};
std::string VulkanVendorString(uint32_t vendorId) {
switch (vendorId) {
case VULKAN_VENDOR_INTEL: return "Intel";
case VULKAN_VENDOR_NVIDIA: return "nVidia";
case VULKAN_VENDOR_AMD: return "AMD";
case VULKAN_VENDOR_ARM: return "ARM";
case VULKAN_VENDOR_QUALCOMM: return "Qualcomm";
case VULKAN_VENDOR_IMGTEC: return "Imagination";
default:
return StringFromFormat("%08x", vendorId);
}
}
VulkanContext::VulkanContext() {
if (!VulkanLoad()) {
init_error_ = "Failed to load Vulkan driver library";
@@ -120,6 +135,11 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32
}
VulkanLoadInstanceFunctions(instance_);
if (!CheckLayers(instance_layer_properties_, instance_layer_names_)) {
WLOG("CheckLayers for instance failed");
// init_error_ = "Failed to validate instance layers";
// return;
}
uint32_t gpu_count = 1;
res = vkEnumeratePhysicalDevices(instance_, &gpu_count, nullptr);
@@ -141,11 +161,6 @@ VkResult VulkanContext::CreateInstance(const char *app_name, int app_ver, uint32
return res;
}
if (!CheckLayers(instance_layer_properties_, instance_layer_names_)) {
WLOG("CheckLayers failed");
// init_error_ = "Failed to validate instance layers";
// return;
}
return VK_SUCCESS;
}
@@ -333,14 +348,47 @@ bool VulkanContext::CheckLayers(const std::vector<LayerProperties> &layer_props,
return true;
}
int VulkanContext::GetBestPhysicalDevice() {
// Rules: Prefer discrete over embedded.
// Prefer nVidia over Intel.
int maxScore = -1;
int best = -1;
for (size_t i = 0; i < physical_devices_.size(); i++) {
int score = 0;
VkPhysicalDeviceProperties props;
vkGetPhysicalDeviceProperties(physical_devices_[i], &props);
switch (props.deviceType) {
case VK_PHYSICAL_DEVICE_TYPE_CPU:
score += 1;
break;
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
score += 20;
break;
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU:
score += 10;
break;
}
if (props.vendorID == VULKAN_VENDOR_AMD) {
score += 5;
} else if (props.vendorID == VULKAN_VENDOR_NVIDIA) {
score += 5;
}
if (score > maxScore) {
best = (int)i;
maxScore = score;
}
}
return best;
}
void VulkanContext::ChooseDevice(int physical_device) {
physical_device_ = physical_device;
GetDeviceLayerProperties();
if (!CheckLayers(device_layer_properties_, device_layer_names_)) {
WLOG("CheckLayers failed (2)");
// init_error_ = "Failed to validate device layers";
// return;
WLOG("CheckLayers for device %d failed", physical_device);
}
vkGetPhysicalDeviceQueueFamilyProperties(physical_devices_[physical_device_], &queue_count, nullptr);
@@ -786,7 +834,8 @@ bool VulkanContext::CreateShaderModule(const std::vector<uint32_t> &spirv, VkSha
void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask,
VkImageLayout oldImageLayout, VkImageLayout newImageLayout,
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask) {
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask,
int numMipLevels) {
VkImageMemoryBarrier image_memory_barrier{ VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
image_memory_barrier.srcAccessMask = srcAccessMask;
image_memory_barrier.dstAccessMask = dstAccessMask;
@@ -795,8 +844,8 @@ void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, VkImageAspectFla
image_memory_barrier.image = image;
image_memory_barrier.subresourceRange.aspectMask = aspectMask;
image_memory_barrier.subresourceRange.baseMipLevel = 0;
image_memory_barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
image_memory_barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
image_memory_barrier.subresourceRange.levelCount = numMipLevels;
image_memory_barrier.subresourceRange.layerCount = 1; // We never use more than one layer, and old Mali drivers have problems with VK_REMAINING_ARRAY_LAYERS/VK_REMAINING_MIP_LEVELS.
image_memory_barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
image_memory_barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
vkCmdPipelineBarrier(cmd, srcStageMask, dstStageMask, 0, 0, nullptr, 0, nullptr, 1, &image_memory_barrier);
@@ -906,11 +955,10 @@ const char *VulkanResultToString(VkResult res) {
case VK_ERROR_OUT_OF_DATE_KHR: return "VK_ERROR_OUT_OF_DATE_KHR";
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "VK_ERROR_INCOMPATIBLE_DISPLAY_KHR";
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "VK_ERROR_NATIVE_WINDOW_IN_USE_KHR";
case VK_ERROR_OUT_OF_POOL_MEMORY_KHR: return "VK_ERROR_OUT_OF_POOL_MEMORY_KHR";
case VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX: return "VK_ERROR_INVALID_EXTERNAL_HANDLE_KHX";
default:
return "Unknown";
return "VK_ERROR_...(unknown)";
}
}
void VulkanAssertImpl(VkResult check, const char *function, const char *file, int line) {
const char *error = "(none)";
}
+16 -3
View File
@@ -43,6 +43,18 @@ enum {
VULKAN_FLAG_PRESENT_FIFO_RELAXED = 8,
};
enum {
VULKAN_VENDOR_NVIDIA = 0x000010de,
VULKAN_VENDOR_INTEL = 0x00008086, // Haha!
VULKAN_VENDOR_AMD = 0x00001002,
VULKAN_VENDOR_ARM = 0x000013B5, // Mali
VULKAN_VENDOR_QUALCOMM = 0x00005143,
VULKAN_VENDOR_IMGTEC = 0x00001010, // PowerVR
};
std::string VulkanVendorString(uint32_t vendorId);
struct VulkanPhysicalDeviceInfo {
VkFormat preferredDepthStencilFormat;
};
@@ -203,8 +215,7 @@ public:
VkResult CreateInstance(const char *app_name, int app_ver, uint32_t flags);
// TODO: Actually do some checks?
int GetBestPhysicalDevice() const { return 0; }
int GetBestPhysicalDevice();
void ChooseDevice(int physical_device);
bool EnableDeviceExtension(const char *extension);
VkResult CreateDevice();
@@ -393,12 +404,14 @@ private:
void TransitionImageLayout2(VkCommandBuffer cmd, VkImage image, VkImageAspectFlags aspectMask,
VkImageLayout oldImageLayout, VkImageLayout newImageLayout,
VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask);
VkAccessFlags srcAccessMask, VkAccessFlags dstAccessMask, int mipLevels = VK_REMAINING_MIP_LEVELS);
// GLSL compiler
void init_glslang();
void finalize_glslang();
bool GLSLtoSPV(const VkShaderStageFlagBits shader_type, const char *pshader, std::vector<uint32_t> &spirv, std::string *errorMessage = nullptr);
const char *VulkanResultToString(VkResult res);
#endif // UTIL_INIT
-1
View File
@@ -407,7 +407,6 @@ static bool DefaultSasThread() {
static ConfigSetting cpuSettings[] = {
ReportedConfigSetting("CPUCore", &g_Config.iCpuCore, &DefaultCpuCore, true, true),
ReportedConfigSetting("SeparateCPUThread", &g_Config.bSeparateCPUThread, false, true, true),
ReportedConfigSetting("SeparateSASThread", &g_Config.bSeparateSASThread, &DefaultSasThread, true, true),
ReportedConfigSetting("SeparateIOThread", &g_Config.bSeparateIOThread, true, true, true),
ReportedConfigSetting("IOTimingMethod", &g_Config.iIOTimingMethod, IOTIMING_REALISTIC, true, true),
-2
View File
@@ -133,8 +133,6 @@ public:
bool bFuncReplacements;
bool bHideSlowWarnings;
// Definitely cannot be changed while game is running.
bool bSeparateCPUThread;
bool bSeparateSASThread;
bool bSeparateIOThread;
int iIOTimingMethod;
+851 -595
View File
File diff suppressed because it is too large. Load diff
+30 -10
View File
@@ -18,25 +18,45 @@ void __CheatDoState(PointerWrap &p);
// Return whether cheats are enabled and in effect.
bool CheatsInEffect();
struct CheatLine {
uint32_t part1;
uint32_t part2;
};
enum class CheatCodeFormat {
UNDEFINED,
CWCHEAT,
TEMPAR,
};
struct CheatCode {
CheatCodeFormat fmt;
std::vector<CheatLine> lines;
};
struct CheatOperation;
class CWCheatEngine {
public:
CWCheatEngine();
std::vector<std::string> GetCodesList();
void CreateCodeList();
void ParseCheats();
void CreateCheatFile();
void Exit();
void Run();
std::vector<int> GetNextCode();
bool HasCheats();
private:
void InvalidateICache(u32 addr, int size);
void SkipCodes(int count);
void SkipAllCodes();
bool exit2, cheatEnabled;
int GetAddress(int value);
std::vector<std::string> codeNameList;
u32 GetAddress(u32 value);
std::vector<std::string> codes, initialCodesList, parts;
size_t currentCode;
CheatOperation InterpretNextOp(const CheatCode &cheat, size_t &i);
CheatOperation InterpretNextCwCheat(const CheatCode &cheat, size_t &i);
CheatOperation InterpretNextTempAR(const CheatCode &cheat, size_t &i);
void ExecuteOp(const CheatOperation &op, const CheatCode &cheat, size_t &i);
void ApplyMemoryOperator(const CheatOperation &op, uint32_t(*oper)(uint32_t, uint32_t));
bool TestIf(const CheatOperation &op, bool(*oper)(int a, int b));
bool TestIfAddr(const CheatOperation &op, bool(*oper)(int a, int b));
std::vector<CheatCode> cheats_;
};
+6 -29
View File
@@ -57,10 +57,6 @@ static int geSyncEvent;
static int geInterruptEvent;
static int geCycleEvent;
// Let's try updating 10 times per vblank - this is the interval for geCycleEvent.
const int geIntervalUs = 1000000 / (60 * 10);
const int geBehindThresholdUs = 1000000 / (60 * 10);
class GeIntrHandler : public IntrHandler {
public:
GeIntrHandler() : IntrHandler(PSP_GE_INTR) {}
@@ -194,19 +190,7 @@ static void __GeExecuteInterrupt(u64 userdata, int cyclesLate) {
}
static void __GeCheckCycles(u64 userdata, int cyclesLate) {
u64 geTicks = gpu->GetTickEstimate();
if (geTicks != 0) {
if (CoreTiming::GetTicks() > geTicks + usToCycles(geBehindThresholdUs)) {
u64 diff = CoreTiming::GetTicks() - geTicks;
// Let the GPU thread catch up.
gpu->SyncThread();
CoreTiming::Advance();
}
}
// This may get out of step if we synced (because we don't correct for cyclesLate),
// but that's okay - __GeCheckCycles is a very rough way to synchronize anyway.
CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0);
// Deprecated
}
void __GeInit() {
@@ -217,15 +201,12 @@ void __GeInit() {
geSyncEvent = CoreTiming::RegisterEvent("GeSyncEvent", &__GeExecuteSync);
geInterruptEvent = CoreTiming::RegisterEvent("GeInterruptEvent", &__GeExecuteInterrupt);
// Deprecated
geCycleEvent = CoreTiming::RegisterEvent("GeCycleEvent", &__GeCheckCycles);
listWaitingThreads.clear();
drawWaitingThreads.clear();
// When we're using separate CPU/GPU threads, we need to keep them in sync.
if (IsOnSeparateCPUThread()) {
CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0);
}
}
struct GeInterruptData_v1 {
@@ -270,20 +251,18 @@ void __GeDoState(PointerWrap &p) {
void __GeShutdown() {
}
// Warning: may be called from the GPU thread, if there is a separate one (multithread mode).
bool __GeTriggerSync(GPUSyncType type, int id, u64 atTicks) {
u64 userdata = (u64)id << 32 | (u64)type;
s64 future = atTicks - CoreTiming::GetTicks();
if (type == GPU_SYNC_DRAW) {
s64 left = CoreTiming::UnscheduleThreadsafeEvent(geSyncEvent, userdata);
s64 left = CoreTiming::UnscheduleEvent(geSyncEvent, userdata);
if (left > future)
future = left;
}
CoreTiming::ScheduleEvent_Threadsafe(future, geSyncEvent, userdata);
CoreTiming::ScheduleEvent(future, geSyncEvent, userdata);
return true;
}
// Warning: may be called from the GPU thread, if there is a separate one (multithread mode).
bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) {
GeInterruptData intrdata;
intrdata.listid = listid;
@@ -293,7 +272,7 @@ bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) {
ge_pending_cb.push_back(intrdata);
u64 userdata = (u64)listid << 32 | (u64) pc;
CoreTiming::ScheduleEvent_Threadsafe(atTicks - CoreTiming::GetTicks(), geInterruptEvent, userdata);
CoreTiming::ScheduleEvent(atTicks - CoreTiming::GetTicks(), geInterruptEvent, userdata);
return true;
}
@@ -504,7 +483,6 @@ static int sceGeUnsetCallback(u32 cbID) {
// unless some insane game pokes it and relies on it...
u32 sceGeSaveContext(u32 ctxAddr) {
DEBUG_LOG(SCEGE, "sceGeSaveContext(%08x)", ctxAddr);
gpu->SyncThread();
if (gpu->BusyDrawing()) {
WARN_LOG(SCEGE, "sceGeSaveContext(%08x): lists in process, aborting", ctxAddr);
@@ -524,7 +502,6 @@ u32 sceGeSaveContext(u32 ctxAddr) {
u32 sceGeRestoreContext(u32 ctxAddr) {
DEBUG_LOG(SCEGE, "sceGeRestoreContext(%08x)", ctxAddr);
gpu->SyncThread();
if (gpu->BusyDrawing()) {
WARN_LOG(SCEGE, "sceGeRestoreContext(%08x): lists in process, aborting", ctxAddr);
+1 -2
View File
@@ -46,8 +46,7 @@ typedef struct PspUsbCamSetupVideoParam {
int evlevel;
} PspUsbCamSetupVideoParam;
static unsigned char sceUsbCamDummyImage[] = {
static const unsigned char sceUsbCamDummyImage[] = {
0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x01, 0x00, 0x60,
0x00, 0x60, 0x00, 0x00, 0xFF, 0xE1, 0x00, 0x68, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x4D, 0x4D,
0x00, 0x2A, 0x00, 0x00, 0x00, 0x08, 0x00, 0x04, 0x01, 0x1A, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01,
+2
View File
@@ -129,6 +129,8 @@ namespace MIPSComp {
}
}
DISABLE;
u32 iaddr = gpr.IsImm(rs) ? offset + gpr.GetImm(rs) : 0xFFFFFFFF;
std::vector<FixupBranch> skips;
+21 -36
View File
@@ -328,7 +328,6 @@ void CPU_RunLoop() {
switch (cpuThreadState) {
case CPU_THREAD_EXECUTE:
mipsr4k.RunLoopUntil(cpuThreadUntil);
gpu->FinishEventLoop();
CPU_NextState(CPU_THREAD_EXECUTE, CPU_THREAD_RUNNING);
break;
@@ -354,12 +353,6 @@ void CPU_RunLoop() {
coreState = CORE_POWERDOWN;
}
// Let's make sure the gpu has already cleaned up before we start freeing memory.
if (gpu) {
gpu->FinishEventLoop();
gpu->SyncThread(true);
}
CPU_Shutdown();
CPU_SetState(CPU_THREAD_NOT_RUNNING);
}
@@ -371,9 +364,9 @@ void Core_UpdateState(CoreState newState) {
Core_UpdateSingleStep();
}
static void Core_UpdateDebugStats(bool flag) {
if (coreCollectDebugStats != flag) {
coreCollectDebugStats = flag;
void Core_UpdateDebugStats(bool collectStats) {
if (coreCollectDebugStats != collectStats) {
coreCollectDebugStats = collectStats;
mipsr4k.ClearJitCache();
}
@@ -384,18 +377,15 @@ static void Core_UpdateDebugStats(bool flag) {
void System_Wake() {
// Ping the threads so they check coreState.
CPU_NextStateNot(CPU_THREAD_NOT_RUNNING, CPU_THREAD_SHUTDOWN);
if (gpu) {
gpu->FinishEventLoop();
}
}
// Ugly!
static bool pspIsInited = false;
static bool pspIsIniting = false;
static bool pspIsQuiting = false;
static bool pspIsQuitting = false;
bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) {
if (pspIsIniting || pspIsQuiting) {
if (pspIsIniting || pspIsQuitting) {
return false;
}
@@ -415,7 +405,9 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) {
coreParameter.errorString = "";
pspIsIniting = true;
if (g_Config.bSeparateCPUThread) {
// Keeping this around because we might need it in the future.
const bool separateCPUThread = false;
if (separateCPUThread) {
Core_ListenShutdown(System_Wake);
CPU_SetState(CPU_THREAD_PENDING);
cpuThread = new std::thread(&CPU_RunLoop);
@@ -438,7 +430,7 @@ bool PSP_InitUpdate(std::string *error_string) {
return true;
}
if (g_Config.bSeparateCPUThread && !CPU_IsReady()) {
if (!CPU_IsReady()) {
return false;
}
@@ -459,7 +451,8 @@ bool PSP_InitUpdate(std::string *error_string) {
bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) {
PSP_InitStart(coreParam, error_string);
if (g_Config.bSeparateCPUThread) {
// For a potential resurrection of separate CPU thread later.
if (false) {
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
}
@@ -472,12 +465,12 @@ bool PSP_IsIniting() {
}
bool PSP_IsInited() {
return pspIsInited && !pspIsQuiting;
return pspIsInited && !pspIsQuitting;
}
void PSP_Shutdown() {
// Do nothing if we never inited.
if (!pspIsInited && !pspIsIniting && !pspIsQuiting) {
if (!pspIsInited && !pspIsIniting && !pspIsQuitting) {
return;
}
@@ -488,7 +481,7 @@ void PSP_Shutdown() {
#endif
// Make sure things know right away that PSP memory, etc. is going away.
pspIsQuiting = true;
pspIsQuitting = true;
if (coreState == CORE_RUNNING)
Core_UpdateState(CORE_ERROR);
Core_NotifyShutdown();
@@ -507,7 +500,7 @@ void PSP_Shutdown() {
currentMIPS = 0;
pspIsInited = false;
pspIsIniting = false;
pspIsQuiting = false;
pspIsQuitting = false;
g_Config.unloadGameConfig();
}
@@ -525,15 +518,14 @@ void PSP_EndHostFrame() {
}
void PSP_RunLoopUntil(u64 globalticks) {
Core_UpdateDebugStats(g_Config.bShowDebugStats || g_Config.bLogFrameDrops);
SaveState::Process();
if (coreState == CORE_POWERDOWN || coreState == CORE_ERROR) {
return;
}
// Switch the CPU thread on or off, as the case may be.
bool useCPUThread = g_Config.bSeparateCPUThread;
// We no longer allow a separate CPU thread but if we add a render queue
// to GL we're gonna need it.
bool useCPUThread = false;
if (useCPUThread && cpuThread == nullptr) {
// Need to start the cpu thread.
Core_ListenShutdown(System_Wake);
@@ -541,9 +533,8 @@ void PSP_RunLoopUntil(u64 globalticks) {
cpuThread = new std::thread(&CPU_RunLoop);
cpuThreadID = cpuThread->get_id();
cpuThread->detach();
if (gpu) {
gpu->SetThreadEnabled(true);
}
// Probably needs to tell the gpu that it will need to queue up its output
// on another thread.
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
} else if (!useCPUThread && cpuThread != nullptr) {
CPU_SetState(CPU_THREAD_QUIT);
@@ -551,21 +542,15 @@ void PSP_RunLoopUntil(u64 globalticks) {
delete cpuThread;
cpuThread = nullptr;
cpuThreadID = std::thread::id();
if (gpu) {
gpu->SetThreadEnabled(false);
}
}
if (cpuThread != nullptr) {
// Tell the gpu a new frame is about to begin, before we start the CPU.
gpu->SyncBeginFrame();
cpuThreadUntil = globalticks;
if (CPU_NextState(CPU_THREAD_RUNNING, CPU_THREAD_EXECUTE)) {
// The CPU doesn't actually respect cpuThreadUntil well, especially when skipping frames.
// TODO: Something smarter? Or force CPU to bail periodically?
while (!CPU_IsReady()) {
gpu->RunEventsUntil(CoreTiming::GetTicks() + msToCycles(1000));
// Have the GPU do stuff here.
if (coreState != CORE_RUNNING) {
CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady);
}
+3
View File
@@ -73,6 +73,9 @@ void PSP_EndHostFrame();
void PSP_RunLoopUntil(u64 globalticks);
void PSP_RunLoopFor(int cycles);
// Call before PSP_BeginHostFrame() in order to not miss any GPU stats.
void Core_UpdateDebugStats(bool collectStats);
void Audio_Init();
bool IsOnSeparateCPUThread();
+3 -1
View File
@@ -1932,6 +1932,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB
bool flipY = (g_Config.iGPUBackend == GPU_BACKEND_OPENGL && !useBufferedRendering_) ? true : false;
buffer.Allocate(w, h, GE_FORMAT_8888, flipY, true);
bool retval = draw_->CopyFramebufferToMemorySync(bound, Draw::FB_COLOR_BIT, 0, 0, w, h, Draw::DataFormat::R8G8B8A8_UNORM, buffer.GetData(), w);
gpuStats.numReadbacks++;
// Vulkan requires us to re-apply all dynamic state for each command buffer, and the above will cause us to start a new cmdbuf.
// So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE);
@@ -2034,6 +2035,7 @@ void FramebufferManagerCommon::PackFramebufferSync_(VirtualFramebuffer *vfb, int
DEBUG_LOG(G3D, "Reading framebuffer to mem, fb_address = %08x", fb_address);
draw_->CopyFramebufferToMemorySync(vfb->fbo, Draw::FB_COLOR_BIT, x, y, w, h, destFormat, destPtr, vfb->fb_stride);
gpuStats.numReadbacks++;
}
void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) {
@@ -2084,7 +2086,7 @@ void FramebufferManagerCommon::DownloadFramebufferForClut(u32 fb_address, u32 lo
FlushBeforeCopy();
// No need to download if we already have it.
if (!vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) {
if (w > 0 && h > 0 && !vfb->memoryUpdated && vfb->clutUpdatedBytes < loadBytes) {
// We intentionally don't call OptimizeDownloadRange() here - we don't want to over download.
// CLUT framebuffers are often incorrectly estimated in size.
if (x == 0 && y == 0 && w == vfb->width && h == vfb->height) {
+1
View File
@@ -400,6 +400,7 @@ void SoftwareTransform(
// rectangle out of many. Quite a small optimization though.
// Experiment: Disable on PowerVR (see issue #6290)
// TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not.
// TODO: Allow creating a depth clear and a color draw.
bool reallyAClear = false;
if (maxIndex > 1 && prim == GE_PRIM_RECTANGLES && gstate.isModeClear()) {
int scissorX2 = gstate.getScissorX2() + 1;
+3 -1
View File
@@ -17,6 +17,7 @@
#pragma once
#include <map>
#include <d3d11.h>
#include <d3d11_1.h>
@@ -190,7 +191,8 @@ private:
PushBufferD3D11 *pushVerts_;
PushBufferD3D11 *pushInds_;
// D3D11 state object caches
// D3D11 state object caches.
// TODO: Change them to DenseHashMaps.
std::map<uint64_t, ID3D11BlendState *> blendCache_;
std::map<uint64_t, ID3D11BlendState1 *> blendCache1_;
std::map<uint64_t, ID3D11DepthStencilState *> depthStencilCache_;
+9 -21
View File
@@ -286,7 +286,7 @@ void GPU_D3D11::DeviceRestore() {
// Nothing needed.
}
void GPU_D3D11::InitClearInternal() {
void GPU_D3D11::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
// device_->Clear(0, NULL, D3DCLEAR_STENCIL | D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0);
@@ -305,8 +305,8 @@ void GPU_D3D11::BeginHostFrame() {
}
}
void GPU_D3D11::ReapplyGfxStateInternal() {
GPUCommon::ReapplyGfxStateInternal();
void GPU_D3D11::ReapplyGfxState() {
GPUCommon::ReapplyGfxState();
// TODO: Dirty our caches for depth states etc
}
@@ -316,8 +316,8 @@ void GPU_D3D11::EndHostFrame() {
draw_->BindPipeline(nullptr);
}
void GPU_D3D11::BeginFrameInternal() {
GPUCommon::BeginFrameInternal();
void GPU_D3D11::BeginFrame() {
GPUCommon::BeginFrame();
textureCacheD3D11_->StartFrame();
drawEngine_.BeginFrame();
@@ -338,13 +338,6 @@ void GPU_D3D11::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat f
}
bool GPU_D3D11::FramebufferDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->dirtyAfterDisplay;
@@ -353,15 +346,8 @@ bool GPU_D3D11::FramebufferDirty() {
}
return true;
}
bool GPU_D3D11::FramebufferReallyDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
bool GPU_D3D11::FramebufferReallyDirty() {
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -371,7 +357,7 @@ bool GPU_D3D11::FramebufferReallyDirty() {
return true;
}
void GPU_D3D11::CopyDisplayToOutputInternal() {
void GPU_D3D11::CopyDisplayToOutput() {
float blendColor[4]{};
context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF);
@@ -727,6 +713,7 @@ void GPU_D3D11::GetStats(char *buffer, size_t bufsize) {
"Cached, Uncached Vertices Drawn: %i, %i\n"
"FBOs active: %i\n"
"Textures active: %i, decoded: %i invalidated: %i\n"
"Readbacks: %d\n"
"Vertex, Fragment shaders loaded: %i, %i\n",
gpuStats.msProcessingDisplayLists * 1000.0f,
gpuStats.numDrawCalls,
@@ -743,6 +730,7 @@ void GPU_D3D11::GetStats(char *buffer, size_t bufsize) {
(int)textureCacheD3D11_->NumLoadedTextures(),
gpuStats.numTexturesDecoded,
gpuStats.numTextureInvalidations,
gpuStats.numReadbacks,
shaderManagerD3D11_->GetNumVertexShaders(),
shaderManagerD3D11_->GetNumFragmentShaders()
);
+4 -4
View File
@@ -40,7 +40,7 @@ public:
void PreExecuteOp(u32 op, u32 diff) override;
void ExecuteOp(u32 op, u32 diff) override;
void ReapplyGfxStateInternal() override;
void ReapplyGfxState() override;
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
void GetStats(char *buffer, size_t bufsize) override;
void ClearCacheNextFrame() override;
@@ -96,9 +96,9 @@ private:
void CheckFlushOp(int cmd, u32 diff);
void BuildReportingInfo();
void InitClearInternal() override;
void BeginFrameInternal() override;
void CopyDisplayToOutputInternal() override;
void InitClear() override;
void BeginFrame() override;
void CopyDisplayToOutput() override;
ID3D11Device *device_;
ID3D11DeviceContext *context_;
-1
View File
@@ -203,7 +203,6 @@ void TextureCacheD3D11::SetFramebufferSamplingParams(u16 bufferWidth, u16 buffer
bool sClamp;
bool tClamp;
float lodBias;
bool autoMip;
GetSamplingParams(minFilt, magFilt, sClamp, tClamp, lodBias, 0, 0);
key.minFilt = minFilt & 1;
+9 -21
View File
@@ -251,7 +251,7 @@ void GPU_DX9::DeviceRestore() {
// Nothing needed.
}
void GPU_DX9::InitClearInternal() {
void GPU_DX9::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
dxstate.depthWrite.set(true);
@@ -272,12 +272,12 @@ void GPU_DX9::BeginHostFrame() {
}
}
void GPU_DX9::ReapplyGfxStateInternal() {
void GPU_DX9::ReapplyGfxState() {
dxstate.Restore();
GPUCommon::ReapplyGfxStateInternal();
GPUCommon::ReapplyGfxState();
}
void GPU_DX9::BeginFrameInternal() {
void GPU_DX9::BeginFrame() {
// Turn off vsync when unthrottled
int desiredVSyncInterval = g_Config.bVSync ? 1 : 0;
if ((PSP_CoreParameter().unthrottle) || (PSP_CoreParameter().fpsLimit == 1))
@@ -292,7 +292,7 @@ void GPU_DX9::BeginFrameInternal() {
depalShaderCache_.Decimate();
// fragmentTestCache_.Decimate();
GPUCommon::BeginFrameInternal();
GPUCommon::BeginFrame();
shaderManagerDX9_->DirtyShader();
framebufferManager_->BeginFrame();
@@ -304,13 +304,6 @@ void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for
}
bool GPU_DX9::FramebufferDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->dirtyAfterDisplay;
@@ -319,15 +312,8 @@ bool GPU_DX9::FramebufferDirty() {
}
return true;
}
bool GPU_DX9::FramebufferReallyDirty() {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
if (ThreadEnabled()) {
// FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause.
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
bool GPU_DX9::FramebufferReallyDirty() {
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -337,7 +323,7 @@ bool GPU_DX9::FramebufferReallyDirty() {
return true;
}
void GPU_DX9::CopyDisplayToOutputInternal() {
void GPU_DX9::CopyDisplayToOutput() {
dxstate.depthWrite.set(true);
dxstate.colorMask.set(true, true, true, true);
@@ -659,6 +645,7 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) {
"Cached, Uncached Vertices Drawn: %i, %i\n"
"FBOs active: %i\n"
"Textures active: %i, decoded: %i invalidated: %i\n"
"Readbacks: %d\n"
"Vertex, Fragment shaders loaded: %i, %i\n",
gpuStats.msProcessingDisplayLists * 1000.0f,
gpuStats.numDrawCalls,
@@ -675,6 +662,7 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) {
(int)textureCacheDX9_->NumLoadedTextures(),
gpuStats.numTexturesDecoded,
gpuStats.numTextureInvalidations,
gpuStats.numReadbacks,
shaderManagerDX9_->GetNumVertexShaders(),
shaderManagerDX9_->GetNumFragmentShaders()
);
+4 -4
View File
@@ -41,7 +41,7 @@ public:
void PreExecuteOp(u32 op, u32 diff) override;
void ExecuteOp(u32 op, u32 diff) override;
void ReapplyGfxStateInternal() override;
void ReapplyGfxState() override;
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
void GetStats(char *buffer, size_t bufsize) override;
void ClearCacheNextFrame() override;
@@ -96,9 +96,9 @@ private:
void CheckFlushOp(int cmd, u32 diff);
void BuildReportingInfo();
void InitClearInternal() override;
void BeginFrameInternal() override;
void CopyDisplayToOutputInternal() override;
void InitClear() override;
void BeginFrame() override;
void CopyDisplayToOutput() override;
LPDIRECT3DDEVICE9 device_;
LPDIRECT3DDEVICE9EX deviceEx_;
+10 -17
View File
@@ -401,13 +401,14 @@ void GPU_GLES::DeviceRestore() {
UpdateVsyncInterval(true);
}
void GPU_GLES::ReinitializeInternal() {
void GPU_GLES::Reinitialize() {
GPUCommon::Reinitialize();
textureCacheGL_->Clear(true);
depalShaderCache_.Clear();
framebufferManagerGL_->DestroyAllFBOs();
}
void GPU_GLES::InitClearInternal() {
void GPU_GLES::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
glstate.depthWrite.set(GL_TRUE);
@@ -467,13 +468,13 @@ void GPU_GLES::UpdateCmdInfo() {
}
}
void GPU_GLES::ReapplyGfxStateInternal() {
void GPU_GLES::ReapplyGfxState() {
drawEngine_.RestoreVAO();
glstate.Restore();
GPUCommon::ReapplyGfxStateInternal();
GPUCommon::ReapplyGfxState();
}
void GPU_GLES::BeginFrameInternal() {
void GPU_GLES::BeginFrame() {
UpdateVsyncInterval(resized_);
resized_ = false;
@@ -483,7 +484,7 @@ void GPU_GLES::BeginFrameInternal() {
depalShaderCache_.Decimate();
fragmentTestCache_.Decimate();
GPUCommon::BeginFrameInternal();
GPUCommon::BeginFrame();
// Save the cache from time to time. TODO: How often?
if (!shaderCachePath_.empty() && (gpuStats.numFlips & 1023) == 0) {
@@ -504,11 +505,6 @@ void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat fo
}
bool GPU_GLES::FramebufferDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->dirtyAfterDisplay;
@@ -519,11 +515,6 @@ bool GPU_GLES::FramebufferDirty() {
}
bool GPU_GLES::FramebufferReallyDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -533,7 +524,7 @@ bool GPU_GLES::FramebufferReallyDirty() {
return true;
}
void GPU_GLES::CopyDisplayToOutputInternal() {
void GPU_GLES::CopyDisplayToOutput() {
// Flush anything left over.
framebufferManagerGL_->RebindFramebuffer();
drawEngine_.Flush();
@@ -893,6 +884,7 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) {
"Cached, Uncached Vertices Drawn: %i, %i\n"
"FBOs active: %i\n"
"Textures active: %i, decoded: %i invalidated: %i\n"
"Readbacks: %d\n"
"Vertex, Fragment, Programs loaded: %i, %i, %i\n",
gpuStats.msProcessingDisplayLists * 1000.0f,
gpuStats.numDrawCalls,
@@ -909,6 +901,7 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) {
(int)textureCacheGL_->NumLoadedTextures(),
gpuStats.numTexturesDecoded,
gpuStats.numTextureInvalidations,
gpuStats.numReadbacks,
shaderManagerGL_->GetNumVertexShaders(),
shaderManagerGL_->GetNumFragmentShaders(),
shaderManagerGL_->GetNumPrograms());
+5 -5
View File
@@ -41,7 +41,7 @@ public:
void PreExecuteOp(u32 op, u32 diff) override;
void ExecuteOp(u32 op, u32 diff) override;
void ReapplyGfxStateInternal() override;
void ReapplyGfxState() override;
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override;
void GetStats(char *buffer, size_t bufsize) override;
@@ -95,10 +95,10 @@ private:
void CheckFlushOp(int cmd, u32 diff);
void BuildReportingInfo();
void InitClearInternal() override;
void BeginFrameInternal() override;
void CopyDisplayToOutputInternal() override;
void ReinitializeInternal() override;
void InitClear() override;
void BeginFrame() override;
void CopyDisplayToOutput() override;
void Reinitialize() override;
inline void UpdateVsyncInterval(bool force);
void UpdateCmdInfo();
+2
View File
@@ -67,6 +67,7 @@ struct GPUStatistics {
numShaderSwitches = 0;
numFlushes = 0;
numTexturesDecoded = 0;
numReadbacks = 0;
msProcessingDisplayLists = 0;
vertexGPUCycles = 0;
otherGPUCycles = 0;
@@ -85,6 +86,7 @@ struct GPUStatistics {
int numTextureSwitches;
int numShaderSwitches;
int numTexturesDecoded;
int numReadbacks;
double msProcessingDisplayLists;
int vertexGPUCycles;
int otherGPUCycles;
+16 -199
View File
@@ -359,11 +359,9 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) :
// The compiler was not rounding the struct size up to an 8 byte boundary, which
// you'd expect due to the int64 field, but the Linux ABI apparently does not require that.
static_assert(sizeof(DisplayList) == 456, "Bad DisplayList size");
listLock.set_enabled(g_Config.bSeparateCPUThread);
Reinitialize();
SetupColorConv();
SetThreadEnabled(g_Config.bSeparateCPUThread);
gstate.Reset();
gstate_c.Reset();
gpuStats.Reset();
@@ -383,16 +381,7 @@ void GPUCommon::EndHostFrame() {
}
void GPUCommon::InitClear() {
ScheduleEvent(GPU_EVENT_INIT_CLEAR);
}
void GPUCommon::CopyDisplayToOutput() {
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
}
void GPUCommon::Reinitialize() {
easy_guard guard(listLock);
memset(dls, 0, sizeof(dls));
for (int i = 0; i < DisplayListMaxCount; ++i) {
dls[i].state = PSP_GE_DL_STATE_NONE;
@@ -400,14 +389,12 @@ void GPUCommon::Reinitialize() {
}
nextListID = 0;
currentList = NULL;
currentList = nullptr;
isbreak = false;
drawCompleteTicks = 0;
busyTicks = 0;
timeSpentStepping_ = 0.0;
interruptsEnabled_ = true;
UpdateTickEstimate(0);
ScheduleEvent(GPU_EVENT_REINITIALIZE);
}
int GPUCommon::EstimatePerVertexCost() {
@@ -440,7 +427,6 @@ int GPUCommon::EstimatePerVertexCost() {
}
void GPUCommon::PopDLQueue() {
easy_guard guard(listLock);
if(!dlQueue.empty()) {
dlQueue.pop_front();
if(!dlQueue.empty()) {
@@ -449,7 +435,7 @@ void GPUCommon::PopDLQueue() {
if (running)
currentList->state = PSP_GE_DL_STATE_RUNNING;
} else {
currentList = NULL;
currentList = nullptr;
}
}
}
@@ -457,7 +443,6 @@ void GPUCommon::PopDLQueue() {
bool GPUCommon::BusyDrawing() {
u32 state = DrawSync(1);
if (state == PSP_GE_LIST_DRAWING || state == PSP_GE_LIST_STALLING) {
easy_guard guard(listLock);
if (currentList && currentList->state != PSP_GE_DL_STATE_PAUSED) {
return true;
}
@@ -474,12 +459,6 @@ void GPUCommon::DumpNextFrame() {
}
u32 GPUCommon::DrawSync(int mode) {
if (ThreadEnabled()) {
// Sync first, because the CPU is usually faster than the emulated GPU.
SyncThread();
}
easy_guard guard(listLock);
if (mode < 0 || mode > 1)
return SCE_KERNEL_ERROR_INVALID_MODE;
@@ -521,7 +500,6 @@ u32 GPUCommon::DrawSync(int mode) {
}
void GPUCommon::CheckDrawSync() {
easy_guard guard(listLock);
if (dlQueue.empty()) {
for (int i = 0; i < DisplayListMaxCount; ++i)
dls[i].state = PSP_GE_DL_STATE_NONE;
@@ -529,12 +507,6 @@ void GPUCommon::CheckDrawSync() {
}
int GPUCommon::ListSync(int listid, int mode) {
if (ThreadEnabled()) {
// Sync first, because the CPU is usually faster than the emulated GPU.
SyncThread();
}
easy_guard guard(listLock);
if (listid < 0 || listid >= DisplayListMaxCount)
return SCE_KERNEL_ERROR_INVALID_ID;
@@ -579,8 +551,7 @@ int GPUCommon::ListSync(int listid, int mode) {
}
int GPUCommon::GetStack(int index, u32 stackPtr) {
easy_guard guard(listLock);
if (currentList == NULL) {
if (!currentList) {
// Seems like it doesn't return an error code?
return 0;
}
@@ -605,7 +576,6 @@ int GPUCommon::GetStack(int index, u32 stackPtr) {
}
u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<PspGeListArgs> args, bool head) {
easy_guard guard(listLock);
// TODO Check the stack values in missing arg and ajust the stack depth
// Check alignment
@@ -704,7 +674,6 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
drawCompleteTicks = (u64)-1;
// TODO save context when starting the list if param is set
guard.unlock();
ProcessDLQueue();
}
@@ -712,7 +681,6 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
}
u32 GPUCommon::DequeueList(int listid) {
easy_guard guard(listLock);
if (listid < 0 || listid >= DisplayListMaxCount || dls[listid].state == PSP_GE_DL_STATE_NONE)
return SCE_KERNEL_ERROR_INVALID_ID;
@@ -736,7 +704,6 @@ u32 GPUCommon::DequeueList(int listid) {
}
u32 GPUCommon::UpdateStall(int listid, u32 newstall) {
easy_guard guard(listLock);
if (listid < 0 || listid >= DisplayListMaxCount || dls[listid].state == PSP_GE_DL_STATE_NONE)
return SCE_KERNEL_ERROR_INVALID_ID;
auto &dl = dls[listid];
@@ -748,14 +715,12 @@ u32 GPUCommon::UpdateStall(int listid, u32 newstall) {
if (dl.signal == PSP_GE_SIGNAL_HANDLER_PAUSE && PSP_CoreParameter().compat.flags().HackFixHangs)
dl.signal = PSP_GE_SIGNAL_HANDLER_SUSPEND;
guard.unlock();
ProcessDLQueue();
return 0;
}
u32 GPUCommon::Continue() {
easy_guard guard(listLock);
if (!currentList)
return 0;
@@ -791,13 +756,11 @@ u32 GPUCommon::Continue() {
return -1;
}
guard.unlock();
ProcessDLQueue();
return 0;
}
u32 GPUCommon::Break(int mode) {
easy_guard guard(listLock);
if (mode < 0 || mode > 1)
return SCE_KERNEL_ERROR_INVALID_MODE;
@@ -886,8 +849,6 @@ bool GPUCommon::InterpretList(DisplayList &list) {
start = time_now_d();
}
easy_guard guard(listLock);
if (list.state == PSP_GE_DL_STATE_PAUSED)
return false;
currentList = &list;
@@ -911,14 +872,12 @@ bool GPUCommon::InterpretList(DisplayList &list) {
list.interrupted = false;
gpuState = list.pc == list.stall ? GPUSTATE_STALL : GPUSTATE_RUNNING;
guard.unlock();
debugRecording_ = GPURecord::IsActive();
const bool useDebugger = host->GPUDebuggingActive() || debugRecording_;
const bool useFastRunLoop = !dumpThisFrame_ && !useDebugger;
while (gpuState == GPUSTATE_RUNNING) {
{
easy_guard innerGuard(listLock);
if (list.pc == list.stall) {
gpuState = GPUSTATE_STALL;
if (PSP_CoreParameter().compat.flags().FlushAtStall) {
@@ -935,7 +894,6 @@ bool GPUCommon::InterpretList(DisplayList &list) {
}
{
easy_guard innerGuard(listLock);
downcount = list.stall == 0 ? 0x0FFFFFFF : (list.stall - list.pc) / 4;
if (gpuState == GPUSTATE_STALL && list.stall != list.pc) {
@@ -965,10 +923,6 @@ bool GPUCommon::InterpretList(DisplayList &list) {
}
void GPUCommon::BeginFrame() {
ScheduleEvent(GPU_EVENT_BEGIN_FRAME);
}
void GPUCommon::BeginFrameInternal() {
if (dumpNextFrame_) {
NOTICE_LOG(G3D, "DUMPING THIS FRAME");
dumpThisFrame_ = true;
@@ -1032,14 +986,6 @@ void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) {
}
void GPUCommon::ReapplyGfxState() {
if (IsOnSeparateCPUThread()) {
ScheduleEvent(GPU_EVENT_REAPPLY_GFX_STATE);
} else {
ReapplyGfxStateInternal();
}
}
void GPUCommon::ReapplyGfxStateInternal() {
// The commands are embedded in the command memory so we can just reexecute the words. Convenient.
// To be safe we pass 0xFFFFFFFF as the diff.
@@ -1070,55 +1016,7 @@ inline void GPUCommon::UpdateState(GPURunState state) {
downcount = 0;
}
void GPUCommon::ProcessEvent(GPUEvent ev) {
switch (ev.type) {
case GPU_EVENT_PROCESS_QUEUE:
ProcessDLQueueInternal();
break;
case GPU_EVENT_REAPPLY_GFX_STATE:
ReapplyGfxStateInternal();
break;
case GPU_EVENT_INIT_CLEAR:
InitClearInternal();
break;
case GPU_EVENT_BEGIN_FRAME:
BeginFrameInternal();
break;
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
CopyDisplayToOutputInternal();
break;
case GPU_EVENT_INVALIDATE_CACHE:
InvalidateCacheInternal(ev.invalidate_cache.addr, ev.invalidate_cache.size, ev.invalidate_cache.type);
break;
case GPU_EVENT_FB_MEMCPY:
PerformMemoryCopyInternal(ev.fb_memcpy.dst, ev.fb_memcpy.src, ev.fb_memcpy.size);
break;
case GPU_EVENT_FB_MEMSET:
PerformMemorySetInternal(ev.fb_memset.dst, ev.fb_memset.v, ev.fb_memset.size);
break;
case GPU_EVENT_FB_STENCIL_UPLOAD:
PerformStencilUploadInternal(ev.fb_stencil_upload.dst, ev.fb_stencil_upload.size);
break;
case GPU_EVENT_REINITIALIZE:
break;
default:
ERROR_LOG_REPORT(G3D, "Unexpected GPU event type: %d", (int)ev);
break;
}
}
int GPUCommon::GetNextListIndex() {
easy_guard guard(listLock);
auto iter = dlQueue.begin();
if (iter != dlQueue.end()) {
return *iter;
@@ -1127,15 +1025,9 @@ int GPUCommon::GetNextListIndex() {
}
}
bool GPUCommon::ProcessDLQueue() {
ScheduleEvent(GPU_EVENT_PROCESS_QUEUE);
return true;
}
void GPUCommon::ProcessDLQueueInternal() {
void GPUCommon::ProcessDLQueue() {
startingTicks = CoreTiming::GetTicks();
cyclesExecuted = 0;
UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted));
// Seems to be correct behaviour to process the list anyway?
if (startingTicks < busyTicks) {
@@ -1149,25 +1041,20 @@ void GPUCommon::ProcessDLQueueInternal() {
if (!InterpretList(l)) {
return;
} else {
easy_guard guard(listLock);
// Some other list could've taken the spot while we dilly-dallied around.
if (l.state != PSP_GE_DL_STATE_QUEUED) {
// At the end, we can remove it from the queue and continue.
dlQueue.erase(std::remove(dlQueue.begin(), dlQueue.end(), listIndex), dlQueue.end());
}
UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted));
}
}
easy_guard guard(listLock);
currentList = NULL;
currentList = nullptr;
drawCompleteTicks = startingTicks + cyclesExecuted;
busyTicks = std::max(busyTicks, drawCompleteTicks);
__GeTriggerSync(GPU_SYNC_DRAW, 1, drawCompleteTicks);
// Since the event is in CoreTiming, we're in sync. Just set 0 now.
UpdateTickEstimate(0);
}
void GPUCommon::PreExecuteOp(u32 op, u32 diff) {
@@ -1187,12 +1074,10 @@ void GPUCommon::Execute_Iaddr(u32 op, u32 diff) {
}
void GPUCommon::Execute_Origin(u32 op, u32 diff) {
easy_guard guard(listLock);
gstate_c.offsetAddr = currentList->pc;
}
void GPUCommon::Execute_Jump(u32 op, u32 diff) {
easy_guard guard(listLock);
const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC);
#ifdef _DEBUG
if (!Memory::IsValidAddress(target)) {
@@ -1207,7 +1092,6 @@ void GPUCommon::Execute_Jump(u32 op, u32 diff) {
void GPUCommon::Execute_BJump(u32 op, u32 diff) {
if (!currentList->bboxResult) {
// bounding box jump.
easy_guard guard(listLock);
const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC);
if (Memory::IsValidAddress(target)) {
UpdatePC(currentList->pc, target - 4);
@@ -1220,7 +1104,6 @@ void GPUCommon::Execute_BJump(u32 op, u32 diff) {
void GPUCommon::Execute_Call(u32 op, u32 diff) {
PROFILE_THIS_SCOPE("gpu_call");
easy_guard guard(listLock);
// Saint Seiya needs correct support for relative calls.
const u32 retval = currentList->pc + 4;
@@ -1259,7 +1142,6 @@ void GPUCommon::Execute_Call(u32 op, u32 diff) {
}
void GPUCommon::Execute_Ret(u32 op, u32 diff) {
easy_guard guard(listLock);
if (currentList->stackptr == 0) {
DEBUG_LOG_REPORT(G3D, "RET: Stack empty!");
} else {
@@ -1281,7 +1163,6 @@ void GPUCommon::Execute_Ret(u32 op, u32 diff) {
void GPUCommon::Execute_End(u32 op, u32 diff) {
Flush();
easy_guard guard(listLock);
const u32 prev = Memory::ReadUnchecked_U32(currentList->pc - 4);
UpdatePC(currentList->pc, currentList->pc);
// Count in a few extra cycles on END.
@@ -1425,7 +1306,7 @@ void GPUCommon::Execute_End(u32 op, u32 diff) {
__GeTriggerSync(GPU_SYNC_LIST, currentList->id, currentList->waitTicks);
if (currentList->started && currentList->context.IsValid()) {
gstate.Restore(currentList->context);
ReapplyGfxStateInternal();
ReapplyGfxState();
}
}
break;
@@ -1606,7 +1487,6 @@ void GPUCommon::Execute_WorldMtxNum(u32 op, u32 diff) {
gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | ((op + count) & 0xF);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1654,7 +1534,6 @@ void GPUCommon::Execute_ViewMtxNum(u32 op, u32 diff) {
gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | ((op + count) & 0xF);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1702,7 +1581,6 @@ void GPUCommon::Execute_ProjMtxNum(u32 op, u32 diff) {
gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | ((op + count) & 0x1F);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1751,7 +1629,6 @@ void GPUCommon::Execute_TgenMtxNum(u32 op, u32 diff) {
gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | ((op + count) & 0xF);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -1818,7 +1695,6 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) {
gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | ((op + count) & 0x7F);
// Skip over the loaded data, it's done now.
easy_guard innerGuard(listLock);
UpdatePC(currentList->pc, currentList->pc + count * 4);
currentList->pc += count * 4;
}
@@ -2034,8 +1910,6 @@ struct DisplayList_v2 {
};
void GPUCommon::DoState(PointerWrap &p) {
easy_guard guard(listLock);
auto s = p.Section("GPUCommon", 1, 4);
if (!s)
return;
@@ -2114,7 +1988,6 @@ void GPUCommon::InterruptStart(int listid) {
interruptRunning = true;
}
void GPUCommon::InterruptEnd(int listid) {
easy_guard guard(listLock);
interruptRunning = false;
isbreak = false;
@@ -2130,13 +2003,11 @@ void GPUCommon::InterruptEnd(int listid) {
__GeTriggerWait(GPU_SYNC_LIST, listid);
}
guard.unlock();
ProcessDLQueue();
}
// TODO: Maybe cleaner to keep this in GE and trigger the clear directly?
void GPUCommon::SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) {
easy_guard guard(listLock);
if (waitType == GPU_SYNC_DRAW && wokeThreads)
{
for (int i = 0; i < DisplayListMaxCount; ++i) {
@@ -2148,7 +2019,6 @@ void GPUCommon::SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) {
}
bool GPUCommon::GetCurrentDisplayList(DisplayList &list) {
easy_guard guard(listLock);
if (!currentList) {
return false;
}
@@ -2159,7 +2029,6 @@ bool GPUCommon::GetCurrentDisplayList(DisplayList &list) {
std::vector<DisplayList> GPUCommon::ActiveDisplayLists() {
std::vector<DisplayList> result;
easy_guard guard(listLock);
for (auto it = dlQueue.begin(), end = dlQueue.end(); it != end; ++it) {
result.push_back(dls[*it]);
}
@@ -2173,7 +2042,6 @@ void GPUCommon::ResetListPC(int listID, u32 pc) {
return;
}
easy_guard guard(listLock);
dls[listID].pc = pc;
}
@@ -2183,7 +2051,6 @@ void GPUCommon::ResetListStall(int listID, u32 stall) {
return;
}
easy_guard guard(listLock);
dls[listID].stall = stall;
}
@@ -2193,7 +2060,6 @@ void GPUCommon::ResetListState(int listID, DisplayListState state) {
return;
}
easy_guard guard(listLock);
dls[listID].state = state;
}
@@ -2345,38 +2211,17 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) {
cyclesExecuted += ((height * width * bpp) * 16) / 10;
}
void GPUCommon::PerformMemoryCopyInternal(u32 dest, u32 src, int size) {
if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
// We use a little hack for Download/Upload using a VRAM mirror.
// Since they're identical we don't need to copy.
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
Memory::Memcpy(dest, src, size);
}
}
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
void GPUCommon::PerformMemorySetInternal(u32 dest, u8 v, int size) {
if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
}
bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) {
// Track stray copies of a framebuffer in RAM. MotoGP does this.
if (framebufferManager_->MayIntersectFramebuffer(src) || framebufferManager_->MayIntersectFramebuffer(dest)) {
if (IsOnSeparateCPUThread()) {
GPUEvent ev(GPU_EVENT_FB_MEMCPY);
ev.fb_memcpy.dst = dest;
ev.fb_memcpy.src = src;
ev.fb_memcpy.size = size;
ScheduleEvent(ev);
// This is a memcpy, so we need to wait for it to complete.
SyncThread();
} else {
PerformMemoryCopyInternal(dest, src, size);
if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) {
// We use a little hack for Download/Upload using a VRAM mirror.
// Since they're identical we don't need to copy.
if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) {
Memory::Memcpy(dest, src, size);
}
}
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
return true;
}
@@ -2389,17 +2234,8 @@ bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) {
// This may indicate a memset, usually to 0, of a framebuffer.
if (framebufferManager_->MayIntersectFramebuffer(dest)) {
Memory::Memset(dest, v, size);
if (IsOnSeparateCPUThread()) {
GPUEvent ev(GPU_EVENT_FB_MEMSET);
ev.fb_memset.dst = dest;
ev.fb_memset.v = v;
ev.fb_memset.size = size;
ScheduleEvent(ev);
// We don't need to wait for the framebuffer to be updated.
} else {
PerformMemorySetInternal(dest, v, size);
if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) {
InvalidateCache(dest, size, GPU_INVALIDATE_HINT);
}
return true;
}
@@ -2430,14 +2266,6 @@ bool GPUCommon::PerformMemoryUpload(u32 dest, int size) {
}
void GPUCommon::InvalidateCache(u32 addr, int size, GPUInvalidationType type) {
GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE);
ev.invalidate_cache.addr = addr;
ev.invalidate_cache.size = size;
ev.invalidate_cache.type = type;
ScheduleEvent(ev);
}
void GPUCommon::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) {
if (size > 0)
textureCache_->Invalidate(addr, size, type);
else
@@ -2462,23 +2290,12 @@ void GPUCommon::NotifyVideoUpload(u32 addr, int size, int width, int format) {
bool GPUCommon::PerformStencilUpload(u32 dest, int size) {
if (framebufferManager_->MayIntersectFramebuffer(dest)) {
if (IsOnSeparateCPUThread()) {
GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD);
ev.fb_stencil_upload.dst = dest;
ev.fb_stencil_upload.size = size;
ScheduleEvent(ev);
} else {
PerformStencilUploadInternal(dest, size);
}
framebufferManager_->NotifyStencilUpload(dest, size);
return true;
}
return false;
}
void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) {
framebufferManager_->NotifyStencilUpload(dest, size);
}
bool GPUCommon::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) {
u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManager_->DisplayFramebufAddr();
int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_->DisplayFramebufStride();
+7 -115
View File
@@ -2,7 +2,6 @@
#include "Common/Common.h"
#include "Common/MemoryUtil.h"
#include "Core/ThreadEventQueue.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
#include "GPU/Common/GPUDebugInterface.h"
@@ -15,8 +14,6 @@
#include <emmintrin.h>
#endif
typedef ThreadEventQueue<GPUInterface, GPUEvent, GPUEventType, GPU_EVENT_INVALID, GPU_EVENT_SYNC_THREAD, GPU_EVENT_FINISH_EVENT_LOOP> GPUThreadEventQueue;
class FramebufferManagerCommon;
class TextureCacheCommon;
class DrawEngineCommon;
@@ -42,7 +39,7 @@ enum {
FLAG_DIRTYONCHANGE = 64, // NOTE: Either this or FLAG_EXECUTE*, not both!
};
class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface {
class GPUCommon : public GPUInterface, public GPUDebugInterface {
public:
GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw);
virtual ~GPUCommon();
@@ -69,7 +66,7 @@ public:
void PreExecuteOp(u32 op, u32 diff) override;
bool InterpretList(DisplayList &list) override;
virtual bool ProcessDLQueue();
void ProcessDLQueue();
u32 UpdateStall(int listid, u32 newstall) override;
u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<PspGeListArgs> args, bool head) override;
u32 DequeueList(int listid) override;
@@ -77,21 +74,13 @@ public:
u32 DrawSync(int mode) override;
int GetStack(int index, u32 stackPtr) override;
void DoState(PointerWrap &p) override;
bool FramebufferDirty() override {
SyncThread();
return true;
}
bool FramebufferReallyDirty() override {
SyncThread();
return true;
}
bool BusyDrawing() override;
u32 Continue() override;
u32 Break(int mode) override;
void ReapplyGfxState() override;
void CopyDisplayToOutput() override;
void InitClear() override;
void CopyDisplayToOutput() override = 0;
void InitClear() override = 0;
bool PerformMemoryCopy(u32 dest, u32 src, int size) override;
bool PerformMemorySet(u32 dest, u8 v, int size) override;
bool PerformMemoryDownload(u32 dest, int size) override;
@@ -116,10 +105,6 @@ public:
void Execute_BoundingBox(u32 op, u32 diff);
void Execute_BlockTransferStart(u32 op, u32 diff);
void Execute_TexScaleU(u32 op, u32 diff);
void Execute_TexScaleV(u32 op, u32 diff);
void Execute_TexOffsetU(u32 op, u32 diff);
void Execute_TexOffsetV(u32 op, u32 diff);
void Execute_TexLevel(u32 op, u32 diff);
void Execute_WorldMtxNum(u32 op, u32 diff);
@@ -142,20 +127,6 @@ public:
// Note: Not virtual!
inline void Flush();
u64 GetTickEstimate() override {
#if defined(_M_X64) || defined(__ANDROID__)
return curTickEst_;
#elif defined(_M_SSE)
__m64 result = *(__m64 *)&curTickEst_;
u64 safeResult = *(u64 *)&result;
_mm_empty();
return safeResult;
#else
std::lock_guard<std::mutex> guard(curTickEstLock_);
return curTickEst_;
#endif
}
#ifdef USE_CRT_DBG
#undef new
#endif
@@ -254,11 +225,7 @@ protected:
}
}
virtual void InitClearInternal() {}
void BeginFrame() override;
virtual void BeginFrameInternal();
virtual void CopyDisplayToOutputInternal() {}
virtual void ReinitializeInternal() {}
// To avoid virtual calls to PreExecuteOp().
virtual void FastRunLoop(DisplayList &list) = 0;
@@ -268,15 +235,10 @@ protected:
void PopDLQueue();
void CheckDrawSync();
int GetNextListIndex();
void ProcessDLQueueInternal();
virtual void ReapplyGfxStateInternal();
virtual void FastLoadBoneMatrix(u32 target);
void ProcessEvent(GPUEvent ev) override;
bool ShouldExitEventLoop() override {
return coreState != CORE_RUNNING;
}
virtual void FinishDeferred() {
}
// TODO: Unify this.
virtual void FinishDeferred() {}
void DoBlockTransfer(u32 skipDrawReason);
@@ -289,53 +251,6 @@ protected:
}
}
void PerformMemoryCopyInternal(u32 dest, u32 src, int size);
void PerformMemorySetInternal(u32 dest, u8 v, int size);
void PerformStencilUploadInternal(u32 dest, int size);
void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type);
// This mutex can be disabled, which is useful for single core mode.
class optional_mutex {
public:
optional_mutex() : enabled_(true) {}
void set_enabled(bool enabled) {
enabled_ = enabled;
}
void lock() {
if (enabled_)
mutex_.lock();
}
void unlock() {
if (enabled_)
mutex_.unlock();
}
private:
std::mutex mutex_;
bool enabled_;
};
// Allows early unlocking with a guard. Do not double unlock.
class easy_guard {
public:
easy_guard(optional_mutex &mtx) : mtx_(mtx), locked_(true) { mtx_.lock(); }
~easy_guard() {
if (locked_)
mtx_.unlock();
}
void unlock() {
if (locked_)
mtx_.unlock();
else
Crash();
locked_ = false;
}
private:
optional_mutex &mtx_;
bool locked_;
};
FramebufferManagerCommon *framebufferManager_;
TextureCacheCommon *textureCache_;
DrawEngineCommon *drawEngineCommon_;
@@ -350,7 +265,6 @@ protected:
DisplayList dls[DisplayListMaxCount];
DisplayList *currentList;
DisplayListQueue dlQueue;
optional_mutex listLock;
bool interruptRunning;
GPURunState gpuState;
@@ -372,28 +286,6 @@ protected:
GEPrimitiveType lastPrim_;
private:
// For CPU/GPU sync.
#ifdef __ANDROID__
alignas(16) std::atomic<u64> curTickEst_;
#else
alignas(16) volatile u64 curTickEst_;
std::mutex curTickEstLock_;
#endif
inline void UpdateTickEstimate(u64 value) {
#if defined(_M_X64) || defined(__ANDROID__)
curTickEst_ = value;
#elif defined(_M_SSE)
__m64 result = *(__m64 *)&value;
*(__m64 *)&curTickEst_ = result;
_mm_empty();
#else
std::lock_guard<std::mutex> guard(curTickEstLock_);
curTickEst_ = value;
#endif
}
// Debug stats.
double timeSteppingStarted_;
double timeSpentStepping_;
-58
View File
@@ -155,56 +155,6 @@ enum GPUInvalidationType {
GPU_INVALIDATE_SAFE,
};
enum GPUEventType {
GPU_EVENT_INVALID,
GPU_EVENT_PROCESS_QUEUE,
GPU_EVENT_INIT_CLEAR,
GPU_EVENT_BEGIN_FRAME,
GPU_EVENT_COPY_DISPLAY_TO_OUTPUT,
GPU_EVENT_REAPPLY_GFX_STATE,
GPU_EVENT_INVALIDATE_CACHE,
GPU_EVENT_FINISH_EVENT_LOOP,
GPU_EVENT_SYNC_THREAD,
GPU_EVENT_FB_MEMCPY,
GPU_EVENT_FB_MEMSET,
GPU_EVENT_FB_STENCIL_UPLOAD,
GPU_EVENT_REINITIALIZE,
};
struct GPUEvent {
GPUEvent(GPUEventType t) : type(t) {}
GPUEventType type;
union {
// GPU_EVENT_INVALIDATE_CACHE
struct {
u32 addr;
int size;
GPUInvalidationType type;
} invalidate_cache;
// GPU_EVENT_FB_MEMCPY
struct {
u32 dst;
u32 src;
int size;
} fb_memcpy;
// GPU_EVENT_FB_MEMSET
struct {
u32 dst;
u8 v;
int size;
} fb_memset;
// GPU_EVENT_FB_STENCIL_UPLOAD
struct {
u32 dst;
int size;
} fb_stencil_upload;
};
operator GPUEventType() const {
return type;
}
};
namespace Draw {
class DrawContext;
}
@@ -225,10 +175,6 @@ public:
virtual void BeginHostFrame() = 0;
virtual void EndHostFrame() = 0;
// Events
virtual void RunEventsUntil(u64 globalticks) = 0;
virtual void FinishEventLoop() = 0;
// Draw queue management
virtual DisplayList* getList(int listid) = 0;
// TODO: Much of this should probably be shared between the different GPU implementations.
@@ -277,9 +223,6 @@ public:
virtual void DeviceLost() = 0;
virtual void DeviceRestore() = 0;
virtual void ReapplyGfxState() = 0;
virtual void SyncThread(bool force = false) = 0;
virtual void SyncBeginFrame() = 0;
virtual u64 GetTickEstimate() = 0;
virtual void DoState(PointerWrap &p) = 0;
// Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*.
@@ -289,7 +232,6 @@ public:
virtual bool FramebufferDirty() = 0;
virtual bool FramebufferReallyDirty() = 0;
virtual bool BusyDrawing() = 0;
virtual void SetThreadEnabled(bool threadEnabled) = 0;
// If any jit is being used inside the GPU.
virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0;
+1
View File
@@ -40,6 +40,7 @@ public:
bool PerformMemoryUpload(u32 dest, int size) override;
bool PerformStencilUpload(u32 dest, int size) override;
void ClearCacheNextFrame() override {}
bool FramebufferDirty() override { return true; }
void DeviceLost() override {}
void DeviceRestore() override {}
+2 -23
View File
@@ -28,6 +28,7 @@
#include "Core/HLE/sceGe.h"
#include "Core/MIPS/MIPS.h"
#include "Core/Reporting.h"
#include "Core/Core.h"
#include "profiler/profiler.h"
#include "thin3d/thin3d.h"
@@ -280,13 +281,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
draw_->BindIndexBuffer(nullptr, 0);
}
void SoftGPU::CopyDisplayToOutput()
{
ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT);
}
void SoftGPU::CopyDisplayToOutputInternal()
{
void SoftGPU::CopyDisplayToOutput() {
// The display always shows 480x272.
CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT);
framebufferDirty_ = false;
@@ -301,17 +296,6 @@ void SoftGPU::CopyDisplayToOutputInternal()
}
}
void SoftGPU::ProcessEvent(GPUEvent ev) {
switch (ev.type) {
case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT:
CopyDisplayToOutputInternal();
break;
default:
GPUCommon::ProcessEvent(ev);
}
}
void SoftGPU::FastRunLoop(DisplayList &list) {
PROFILE_THIS_SCOPE("soft_runloop");
for (; downcount > 0; --downcount) {
@@ -913,11 +897,6 @@ bool SoftGPU::PerformStencilUpload(u32 dest, int size)
}
bool SoftGPU::FramebufferDirty() {
if (g_Config.bSeparateCPUThread) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
if (g_Config.iFrameSkip != 0) {
bool dirty = framebufferDirty_;
framebufferDirty_ = false;
-3
View File
@@ -94,12 +94,9 @@ public:
protected:
void FastRunLoop(DisplayList &list) override;
void ProcessEvent(GPUEvent ev) override;
void CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight);
private:
void CopyDisplayToOutputInternal() override;
bool framebufferDirty_;
u32 displayFramebuf_;
u32 displayStride_;
+1 -1
View File
@@ -986,11 +986,11 @@ void DrawEngineVulkan::DoFlush() {
Draw::NativeObject object = g_Config.iRenderingMode != 0 ? Draw::NativeObject::FRAMEBUFFER_RENDERPASS : Draw::NativeObject::BACKBUFFER_RENDERPASS;
VkRenderPass renderPass = (VkRenderPass)draw_->GetNativeObject(object);
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(pipelineLayout_, renderPass, pipelineKey_, dec_, vshader, fshader, false);
renderManager->BindPipeline(pipeline->pipeline);
if (!pipeline) {
// Already logged, let's bail out.
return;
}
renderManager->BindPipeline(pipeline->pipeline);
if (pipeline != lastPipeline_) {
if (lastPipeline_ && !lastPipeline_->useBlendConstant && pipeline->useBlendConstant) {
gstate_c.Dirty(DIRTY_BLEND_STATE);
+10 -20
View File
@@ -177,7 +177,9 @@ void GPU_Vulkan::CheckGPUFeatures() {
features |= GPU_SUPPORTS_WIDE_LINES;
}
if (vulkan_->GetFeaturesEnabled().dualSrcBlend) {
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
// Work around for Intel driver bug. See issue #10074.
if (vulkan_->GetPhysicalDeviceProperties().vendorID != VULKAN_VENDOR_INTEL)
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
}
if (vulkan_->GetFeaturesEnabled().logicOp) {
features |= GPU_SUPPORTS_LOGIC_OP;
@@ -332,21 +334,17 @@ void GPU_Vulkan::BuildReportingInfo() {
Reporting::UpdateConfig();
}
void GPU_Vulkan::ReinitializeInternal() {
void GPU_Vulkan::Reinitialize() {
GPUCommon::Reinitialize();
textureCacheVulkan_->Clear(true);
depalShaderCache_.Clear();
framebufferManagerVulkan_->DestroyAllFBOs();
}
void GPU_Vulkan::InitClearInternal() {
void GPU_Vulkan::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
/*
glstate.depthWrite.set(GL_TRUE);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
*/
// TODO?
}
}
@@ -370,11 +368,6 @@ void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat
}
bool GPU_Vulkan::FramebufferDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->dirtyAfterDisplay;
@@ -385,11 +378,6 @@ bool GPU_Vulkan::FramebufferDirty() {
}
bool GPU_Vulkan::FramebufferReallyDirty() {
if (ThreadEnabled()) {
// Allow it to process fully before deciding if it's dirty.
SyncThread();
}
VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB();
if (vfb) {
bool dirty = vfb->reallyDirtyAfterDisplay;
@@ -399,7 +387,7 @@ bool GPU_Vulkan::FramebufferReallyDirty() {
return true;
}
void GPU_Vulkan::CopyDisplayToOutputInternal() {
void GPU_Vulkan::CopyDisplayToOutput() {
// Flush anything left over.
drawEngine_.Flush();
@@ -847,6 +835,7 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
"Cached, Uncached Vertices Drawn: %i, %i\n"
"FBOs active: %i\n"
"Textures active: %i, decoded: %i invalidated: %i\n"
"Readbacks: %d\n"
"Vertex, Fragment, Pipelines loaded: %i, %i, %i\n"
"Pushbuffer space used: UBO %d, Vtx %d, Idx %d\n",
gpuStats.msProcessingDisplayLists * 1000.0f,
@@ -864,6 +853,7 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
(int)textureCacheVulkan_->NumLoadedTextures(),
gpuStats.numTexturesDecoded,
gpuStats.numTextureInvalidations,
gpuStats.numReadbacks,
shaderManagerVulkan_->GetNumVertexShaders(),
shaderManagerVulkan_->GetNumFragmentShaders(),
pipelineManager_->GetNumPipelines(),
+3 -3
View File
@@ -96,9 +96,9 @@ private:
}
void CheckFlushOp(int cmd, u32 diff);
void BuildReportingInfo();
void InitClearInternal() override;
void CopyDisplayToOutputInternal() override;
void ReinitializeInternal() override;
void InitClear() override;
void CopyDisplayToOutput() override;
void Reinitialize() override;
inline void UpdateVsyncInterval(bool force);
void UpdateCmdInfo();
+2 -1
View File
@@ -281,7 +281,7 @@ static VulkanPipeline *CreateVulkanPipeline(VkDevice device, VkPipelineCache pip
VkPipeline pipeline;
VkResult result = vkCreateGraphicsPipelines(device, pipelineCache, 1, &pipe, nullptr, &pipeline);
if (result != VK_SUCCESS) {
ERROR_LOG(G3D, "Failed creating graphics pipeline!");
ERROR_LOG(G3D, "Failed creating graphics pipeline! result='%s'", VulkanResultToString(result));
return nullptr;
}
@@ -321,6 +321,7 @@ VulkanPipeline *PipelineManagerVulkan::GetOrCreatePipeline(VkPipelineLayout layo
VulkanPipeline *pipeline = CreateVulkanPipeline(
vulkan_->GetDevice(), pipelineCache_, layout, renderPass,
rasterKey, vtxDec, vs, fs, useHwTransform);
// Even if the result is nullptr, insert it so we don't try to create it repeatedly.
pipelines_.Insert(key, pipeline);
return pipeline;
}
+1
View File
@@ -155,6 +155,7 @@ UI::EventReturn CwCheatScreen::OnEnableAll(UI::EventParams &params) {
}
fs.close();
g_Config.bReloadCheats = true;
return UI::EVENT_DONE;
}
+10 -8
View File
@@ -1014,10 +1014,13 @@ void EmuScreen::postRender() {
void EmuScreen::render() {
using namespace Draw;
DrawContext *thin3d = screenManager()->getDrawContext();
if (invalid_) {
// It's possible this might be set outside PSP_RunLoopFor().
// In this case, we need to double check it here.
checkPowerDown();
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR });
return;
}
@@ -1032,6 +1035,8 @@ void EmuScreen::render() {
}
}
Core_UpdateDebugStats(g_Config.bShowDebugStats || g_Config.bLogFrameDrops);
PSP_BeginHostFrame();
// We just run the CPU until we get to vblank. This will quickly sync up pretty nicely.
@@ -1047,22 +1052,19 @@ void EmuScreen::render() {
if (coreState == CORE_NEXTFRAME) {
// set back to running for the next frame
coreState = CORE_RUNNING;
} else {
// Didn't actually reach the end of the frame, ran out of the blockTicks cycles.
// In this case we need to bind and wipe the backbuffer, at least.
// It's possible we never ended up outputted anything - make sure we have the backbuffer cleared
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR });
}
checkPowerDown();
PSP_EndHostFrame();
if (invalid_)
return;
// Here the backbuffer will always be bound.
if (!osm.IsEmpty() || g_Config.bShowDebugStats || g_Config.iShowFPSCounter || g_Config.bShowTouchControls || g_Config.bShowDeveloperMenu || g_Config.bShowAudioDebug || saveStatePreview_->GetVisibility() != UI::V_GONE || g_Config.bShowFrameProfiler) {
DrawContext *thin3d = screenManager()->getDrawContext();
// It's possible we never ended up outputted anything - make sure we have the backbuffer.
thin3d->BindFramebufferAsRenderTarget(nullptr, { RPAction::KEEP, RPAction::KEEP });
// This sets up some important states but not the viewport.
screenManager()->getUIContext()->Begin();
+1 -7
View File
@@ -670,13 +670,7 @@ void GameSettingsScreen::CreateViews() {
systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory (Unstable)")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting);
auto separateCPUThread = new CheckBox(&g_Config.bSeparateCPUThread, sy->T("Multithreaded (experimental)"));
systemSettings->Add(separateCPUThread);
separateCPUThread->OnClick.Add([=](EventParams &e) {
if (g_Config.bSeparateCPUThread)
settingInfo_->Show(sy->T("Multithreaded Tip", "Not always faster, causes glitches/crashing"), e.v);
return UI::EVENT_CONTINUE;
});
systemSettings->Add(new CheckBox(&g_Config.bSeparateIOThread, sy->T("I/O on thread (experimental)")))->SetEnabled(!PSP_IsInited());
static const char *ioTimingMethods[] = { "Fast (lag on slow storage)", "Host (bugs, less lag)", "Simulate UMD delays" };
View *ioTimingMethod = systemSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("IO timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), sy->GetName(), screenManager()));
+1 -5
View File
@@ -323,7 +323,6 @@
<ClInclude Include="..\..\ext\glslang\hlsl\hlslGrammar.h" />
<ClInclude Include="..\..\ext\glslang\hlsl\hlslOpMap.h" />
<ClInclude Include="..\..\ext\glslang\hlsl\hlslParseables.h" />
<ClInclude Include="..\..\ext\glslang\hlsl\hlslParseHelper.h" />
<ClInclude Include="..\..\ext\glslang\hlsl\hlslScanContext.h" />
<ClInclude Include="..\..\ext\glslang\hlsl\hlslTokens.h" />
<ClInclude Include="..\..\ext\glslang\hlsl\hlslTokenStream.h" />
@@ -365,9 +364,7 @@
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\Pp.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpAtom.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpContext.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpMemory.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpScanner.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpSymbols.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpTokens.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\propagateNoContraction.cpp" />
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\reflection.cpp" />
@@ -381,7 +378,6 @@
<ClCompile Include="..\..\ext\glslang\hlsl\hlslGrammar.cpp" />
<ClCompile Include="..\..\ext\glslang\hlsl\hlslOpMap.cpp" />
<ClCompile Include="..\..\ext\glslang\hlsl\hlslParseables.cpp" />
<ClCompile Include="..\..\ext\glslang\hlsl\hlslParseHelper.cpp" />
<ClCompile Include="..\..\ext\glslang\hlsl\hlslScanContext.cpp" />
<ClCompile Include="..\..\ext\glslang\hlsl\hlslTokenStream.cpp" />
<ClCompile Include="..\..\ext\glslang\OGLCompilersDLL\InitializeDll.cpp" />
@@ -407,4 +403,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+1 -13
View File
@@ -103,15 +103,9 @@
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpContext.cpp">
<Filter>glslang\MachineIndependent\Preprocessor</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpMemory.cpp">
<Filter>glslang\MachineIndependent\Preprocessor</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpScanner.cpp">
<Filter>glslang\MachineIndependent\Preprocessor</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpSymbols.cpp">
<Filter>glslang\MachineIndependent\Preprocessor</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\glslang\glslang\MachineIndependent\preprocessor\PpTokens.cpp">
<Filter>glslang\MachineIndependent\Preprocessor</Filter>
</ClCompile>
@@ -154,9 +148,6 @@
<ClCompile Include="..\..\ext\glslang\hlsl\hlslParseables.cpp">
<Filter>hlsl</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\glslang\hlsl\hlslParseHelper.cpp">
<Filter>hlsl</Filter>
</ClCompile>
<ClCompile Include="..\..\ext\glslang\hlsl\hlslScanContext.cpp">
<Filter>hlsl</Filter>
</ClCompile>
@@ -314,9 +305,6 @@
<ClInclude Include="..\..\ext\glslang\hlsl\hlslParseables.h">
<Filter>hlsl</Filter>
</ClInclude>
<ClInclude Include="..\..\ext\glslang\hlsl\hlslParseHelper.h">
<Filter>hlsl</Filter>
</ClInclude>
<ClInclude Include="..\..\ext\glslang\hlsl\hlslScanContext.h">
<Filter>hlsl</Filter>
</ClInclude>
@@ -330,4 +318,4 @@
<Filter>OGLCompilersDLL</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>
+1 -3
View File
@@ -30,8 +30,6 @@ android {
}
} else {
release {
// Can't build release builds without a key store.
println 'This build type should only be invoked from CI. Use Optimized builds instead.'
}
}
}
@@ -137,5 +135,5 @@ afterEvaluate {
android.sourceSets.main.assets.getSrcDirs().each { println it }
}
dependencies {
compile project(':com.bda.controller')
implementation project(':com.bda.controller')
}
+10 -1
View File
@@ -290,12 +290,21 @@ bool AndroidVulkanContext::Init(ANativeWindow *wnd, int desiredBackbufferSizeX,
return false;
}
g_Vulkan->ChooseDevice(g_Vulkan->GetBestPhysicalDevice());
int physicalDevice = g_Vulkan->GetBestPhysicalDevice();
if (physicalDevice < 0) {
ELOG("No usable Vulkan device found.");
delete g_Vulkan;
g_Vulkan = nullptr;
return false;
}
g_Vulkan->ChooseDevice(physicalDevice);
// Here we can enable device extensions if we like.
ILOG("Creating vulkan device");
if (g_Vulkan->CreateDevice() != VK_SUCCESS) {
ILOG("Failed to create vulkan device: %s", g_Vulkan->InitError().c_str());
System_SendMessage("toast", "No Vulkan driver found. Using OpenGL instead.");
delete g_Vulkan;
g_Vulkan = nullptr;
return false;
@@ -57,6 +57,7 @@ public class TextRenderer {
int [] pixels = new int[w * h];
bmp.getPixels(pixels, 0, w, 0, 0, w, h);
bmp.recycle();
return pixels;
}
}
-3
View File
@@ -33,16 +33,13 @@ LOCAL_SRC_FILES := \
../glslang/glslang/MachineIndependent/preprocessor/Pp.cpp \
../glslang/glslang/MachineIndependent/preprocessor/PpAtom.cpp \
../glslang/glslang/MachineIndependent/preprocessor/PpContext.cpp \
../glslang/glslang/MachineIndependent/preprocessor/PpMemory.cpp \
../glslang/glslang/MachineIndependent/preprocessor/PpScanner.cpp \
../glslang/glslang/MachineIndependent/preprocessor/PpSymbols.cpp \
../glslang/glslang/MachineIndependent/preprocessor/PpTokens.cpp \
../glslang/glslang/OSDependent/Unix/ossource.cpp \
../glslang/hlsl/hlslAttributes.cpp \
../glslang/hlsl/hlslGrammar.cpp \
../glslang/hlsl/hlslOpMap.cpp \
../glslang/hlsl/hlslParseables.cpp \
../glslang/hlsl/hlslParseHelper.cpp \
../glslang/hlsl/hlslScanContext.cpp \
../glslang/hlsl/hlslTokenStream.cpp \
../glslang/SPIRV/disassemble.cpp \
+2 -5
View File
@@ -22,7 +22,8 @@
<ProjectGuid>{EDFA2E87-8AC1-4853-95D4-D7594FF81947}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>glslang</RootNamespace>
<WindowsTargetPlatformVersion></WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>
</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
@@ -168,9 +169,7 @@
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\Pp.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpAtom.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpContext.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpMemory.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpScanner.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpSymbols.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpTokens.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\propagateNoContraction.cpp" />
<ClCompile Include="glslang\glslang\MachineIndependent\reflection.cpp" />
@@ -184,7 +183,6 @@
<ClCompile Include="glslang\hlsl\hlslGrammar.cpp" />
<ClCompile Include="glslang\hlsl\hlslOpMap.cpp" />
<ClCompile Include="glslang\hlsl\hlslParseables.cpp" />
<ClCompile Include="glslang\hlsl\hlslParseHelper.cpp" />
<ClCompile Include="glslang\hlsl\hlslScanContext.cpp" />
<ClCompile Include="glslang\hlsl\hlslTokenStream.cpp" />
<ClCompile Include="glslang\OGLCompilersDLL\InitializeDll.cpp" />
@@ -231,7 +229,6 @@
<ClInclude Include="glslang\hlsl\hlslGrammar.h" />
<ClInclude Include="glslang\hlsl\hlslOpMap.h" />
<ClInclude Include="glslang\hlsl\hlslParseables.h" />
<ClInclude Include="glslang\hlsl\hlslParseHelper.h" />
<ClInclude Include="glslang\hlsl\hlslScanContext.h" />
<ClInclude Include="glslang\hlsl\hlslTokens.h" />
<ClInclude Include="glslang\hlsl\hlslTokenStream.h" />
-12
View File
@@ -42,15 +42,9 @@
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpContext.cpp">
<Filter>glslang</Filter>
</ClCompile>
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpMemory.cpp">
<Filter>glslang</Filter>
</ClCompile>
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpScanner.cpp">
<Filter>glslang</Filter>
</ClCompile>
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpSymbols.cpp">
<Filter>glslang</Filter>
</ClCompile>
<ClCompile Include="glslang\glslang\MachineIndependent\preprocessor\PpTokens.cpp">
<Filter>glslang</Filter>
</ClCompile>
@@ -137,9 +131,6 @@
<ClCompile Include="glslang\hlsl\hlslParseables.cpp">
<Filter>HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\hlsl\hlslParseHelper.cpp">
<Filter>HLSL</Filter>
</ClCompile>
<ClCompile Include="glslang\hlsl\hlslScanContext.cpp">
<Filter>HLSL</Filter>
</ClCompile>
@@ -290,9 +281,6 @@
<ClInclude Include="glslang\hlsl\hlslParseables.h">
<Filter>HLSL</Filter>
</ClInclude>
<ClInclude Include="glslang\hlsl\hlslParseHelper.h">
<Filter>HLSL</Filter>
</ClInclude>
<ClInclude Include="glslang\hlsl\hlslScanContext.h">
<Filter>HLSL</Filter>
</ClInclude>
+1 -3
View File
@@ -164,9 +164,6 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
std::string text(NormalizeString(std::string(str)));
if (text.empty())
return;
JNIEnv *env;
int result = javaVM->GetEnv((void **)&env, JNI_VERSION_1_6);
assert(env == env_);
uint32_t stringHash = hash::Adler32((const uint8_t *)text.data(), text.size());
uint32_t entryHash = stringHash ^ fontHash_ ^ (align << 24);
@@ -221,6 +218,7 @@ void TextDrawerAndroid::DrawString(DrawBuffer &target, const char *str, float x,
}
}
env_->ReleaseIntArrayElements(imageData, jimage, 0);
env_->DeleteLocalRef(imageData);
desc.initData.push_back((uint8_t *)bitmapData);
entry->texture = draw_->CreateTexture(desc);
delete[] bitmapData;
+21 -16
View File
@@ -2,6 +2,8 @@
#include "VulkanQueueRunner.h"
#include "VulkanRenderManager.h"
// Debug help: adb logcat -s DEBUG NativeActivity NativeApp PPSSPP
// TODO: This is only enough for 4x render resolution / 4x texture upscale for debugger.
// Maybe we should use a dynamically allocated one for larger?
const uint32_t readbackBufferSize = 2048 * 2048 * 4;
@@ -342,6 +344,12 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
iter.fb->Release();
}
// Don't execute empty renderpasses.
if (step.commands.empty() && step.render.color == VKRRenderPassAction::KEEP && step.render.depthStencil == VKRRenderPassAction::KEEP) {
// Nothing to do.
return;
}
// This is supposed to bind a vulkan render pass to the command buffer.
PerformBindFramebufferAsRenderTarget(step, cmd);
@@ -481,28 +489,17 @@ void VulkanQueueRunner::PerformRenderPass(const VKRStep &step, VkCommandBuffer c
}
void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step, VkCommandBuffer cmd) {
VkRenderPass renderPass;
int numClearVals = 0;
VkClearValue clearVal[2]{};
VkFramebuffer framebuf;
int w;
int h;
VkImageLayout prevLayout;
if (step.render.framebuffer) {
VKRFramebuffer *fb = step.render.framebuffer;
framebuf = fb->framebuf;
w = fb->width;
h = fb->height;
prevLayout = fb->color.layout;
} else {
framebuf = backbuffer_;
w = vulkan_->GetBackbufferWidth();
h = vulkan_->GetBackbufferHeight();
}
VkRenderPass renderPass;
int numClearVals = 0;
VkClearValue clearVal[2];
memset(clearVal, 0, sizeof(clearVal));
if (step.render.framebuffer) {
VKRFramebuffer *fb = step.render.framebuffer;
// Now, if the image needs transitioning, let's transition.
// The backbuffer does not, that's handled by VulkanContext.
if (step.render.framebuffer->color.layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) {
@@ -526,15 +523,17 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
break;
}
// Due to a known bug in the Mali driver, pass the level count explicitly.
TransitionImageLayout2(cmd, fb->color.image, VK_IMAGE_ASPECT_COLOR_BIT,
fb->color.layout, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
srcStage, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
srcAccessMask, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT);
srcAccessMask, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, 1);
fb->color.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
}
if (fb->depth.layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) {
VkAccessFlags srcAccessMask;
VkPipelineStageFlags srcStage;
switch (fb->depth.layout) {
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
srcAccessMask = VK_ACCESS_SHADER_READ_BIT;
@@ -552,10 +551,13 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
Crash();
break;
}
// Due to a known bug in the Mali driver, pass the level count explicitly (last param).
TransitionImageLayout2(cmd, fb->depth.image, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
fb->depth.layout, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
srcStage, VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT,
srcAccessMask, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT);
srcAccessMask, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT,
1);
fb->depth.layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
}
@@ -570,6 +572,9 @@ void VulkanQueueRunner::PerformBindFramebufferAsRenderTarget(const VKRStep &step
numClearVals = 2;
}
} else {
framebuf = backbuffer_;
w = vulkan_->GetBackbufferWidth();
h = vulkan_->GetBackbufferHeight();
renderPass = GetBackbufferRenderPass();
assert(step.render.color == VKRRenderPassAction::CLEAR || step.render.color == VKRRenderPassAction::DONT_CARE);
assert(step.render.depthStencil == VKRRenderPassAction::CLEAR || step.render.depthStencil == VKRRenderPassAction::DONT_CARE);
+44 -24
View File
@@ -12,7 +12,7 @@
#endif
// TODO: Using a thread here is unfinished and does not work correctly.
const bool useThread = false;
const bool useThread = true;
#ifndef UINT64_MAX
#define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL
@@ -217,13 +217,15 @@ void VulkanRenderManager::StopThread(bool shutdown) {
thread_.join();
VLOG("thread joined.");
// Resignal fences for next time around - must be done after join.
// Wait for any fences to finish and be resignaled, so we don't have sync issues.
for (int i = 0; i < vulkan_->GetInflightFrames(); i++) {
auto &frameData = frameData_[i];
frameData.readyForRun = false;
if (!shutdown && !frameData.readyForFence) {
vkDestroyFence(vulkan_->GetDevice(), frameData.fence, nullptr);
frameData.fence = vulkan_->CreateFence(true);
std::unique_lock<std::mutex> lock(frameData.push_mutex);
while (!frameData.readyForFence) {
VLOG("PUSH: Waiting for frame[%d].readyForFence = 1 (stop)", i);
frameData.push_condVar.wait(lock);
}
}
}
@@ -268,12 +270,11 @@ VulkanRenderManager::~VulkanRenderManager() {
queueRunner_.DestroyDeviceObjects();
}
// TODO: Activate this code.
void VulkanRenderManager::ThreadFunc() {
setCurrentThreadName("RenderMan");
int threadFrame = threadInitFrame_;
bool nextFrame = false;
while (run_) {
while (true) {
{
if (nextFrame) {
threadFrame++;
@@ -286,6 +287,10 @@ void VulkanRenderManager::ThreadFunc() {
VLOG("PULL: Waiting for frame[%d].readyForRun", threadFrame);
frameData.pull_condVar.wait(lock);
}
if (!frameData.readyForRun && !run_) {
// This means we're out of frames to render and run_ is false, so bail.
break;
}
VLOG("PULL: frame[%d].readyForRun = false", threadFrame);
frameData.readyForRun = false;
// Previously we had a quick exit here that avoided calling Run() if run_ was suddenly false,
@@ -586,11 +591,17 @@ void VulkanRenderManager::BlitFramebuffer(VKRFramebuffer *src, VkRect2D srcRect,
_dbg_assert_msg_(G3D, srcRect.offset.x + srcRect.extent.width <= (uint32_t)src->width, "srcrect offset x + extent > width");
_dbg_assert_msg_(G3D, srcRect.offset.y + srcRect.extent.height <= (uint32_t)src->height, "srcrect offset y + extent > height");
_dbg_assert_msg_(G3D, srcRect.extent.width > 0, "blit srcwidth == 0");
_dbg_assert_msg_(G3D, srcRect.extent.height > 0, "blit srcheight == 0");
_dbg_assert_msg_(G3D, dstRect.offset.x >= 0, "dstrect offset x < 0");
_dbg_assert_msg_(G3D, dstRect.offset.y >= 0, "dstrect offset y < 0");
_dbg_assert_msg_(G3D, dstRect.offset.x + dstRect.extent.width <= (uint32_t)dst->width, "dstrect offset x + extent > width");
_dbg_assert_msg_(G3D, dstRect.offset.y + dstRect.extent.height <= (uint32_t)dst->height, "dstrect offset y + extent > height");
_dbg_assert_msg_(G3D, dstRect.extent.width > 0, "blit dstwidth == 0");
_dbg_assert_msg_(G3D, dstRect.extent.height > 0, "blit dstheight == 0");
VKRStep *step = new VKRStep{ VKRStepType::BLIT };
step->blit.aspectMask = aspectMask;
@@ -650,7 +661,6 @@ void VulkanRenderManager::Finish() {
}
void VulkanRenderManager::Wipe() {
int curFrame = vulkan_->GetCurFrame();
for (auto step : steps_) {
// Need to release held framebuffers.
switch (step->stepType) {
@@ -689,7 +699,13 @@ void VulkanRenderManager::BeginSubmitFrame(int frame) {
// Get the index of the next available swapchain image, and a semaphore to block command buffer execution on.
// Now, I wonder if we should do this early in the frame or late? Right now we do it early, which should be fine.
VkResult res = vkAcquireNextImageKHR(vulkan_->GetDevice(), vulkan_->GetSwapchain(), UINT64_MAX, acquireSemaphore_, (VkFence)VK_NULL_HANDLE, &frameData.curSwapchainImage);
assert(res == VK_SUCCESS);
if (res == VK_SUBOPTIMAL_KHR) {
// Hopefully the resize will happen shortly. Ignore.
} else if (res == VK_ERROR_OUT_OF_DATE_KHR) {
frameData.skipSwap = true;
} else {
assert(res == VK_SUCCESS);
}
// TODO: Deal with the VK_SUBOPTIMAL_KHR and VK_ERROR_OUT_OF_DATE_KHR
// return codes
@@ -737,7 +753,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
cmdBufs[numCmdBufs++] = frameData.mainCmd;
VkSubmitInfo submit_info{ VK_STRUCTURE_TYPE_SUBMIT_INFO };
if (triggerFence) {
if (triggerFence && !frameData.skipSwap) {
submit_info.waitSemaphoreCount = 1;
submit_info.pWaitSemaphores = &acquireSemaphore_;
VkPipelineStageFlags waitStage[1]{ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT };
@@ -745,7 +761,7 @@ void VulkanRenderManager::Submit(int frame, bool triggerFence) {
}
submit_info.commandBufferCount = (uint32_t)numCmdBufs;
submit_info.pCommandBuffers = cmdBufs;
if (triggerFence) {
if (triggerFence && !frameData.skipSwap) {
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &renderingCompleteSemaphore_;
}
@@ -771,21 +787,25 @@ void VulkanRenderManager::EndSubmitFrame(int frame) {
Submit(frame, true);
VkSwapchainKHR swapchain = vulkan_->GetSwapchain();
VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
present.swapchainCount = 1;
present.pSwapchains = &swapchain;
present.pImageIndices = &frameData.curSwapchainImage;
present.pWaitSemaphores = &renderingCompleteSemaphore_;
present.waitSemaphoreCount = 1;
if (!frameData.skipSwap) {
VkSwapchainKHR swapchain = vulkan_->GetSwapchain();
VkPresentInfoKHR present = { VK_STRUCTURE_TYPE_PRESENT_INFO_KHR };
present.swapchainCount = 1;
present.pSwapchains = &swapchain;
present.pImageIndices = &frameData.curSwapchainImage;
present.pWaitSemaphores = &renderingCompleteSemaphore_;
present.waitSemaphoreCount = 1;
VkResult res = vkQueuePresentKHR(vulkan_->GetGraphicsQueue(), &present);
// TODO: Deal with the VK_SUBOPTIMAL_WSI and VK_ERROR_OUT_OF_DATE_WSI
// return codes
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
// ignore, it'll be fine. this happens sometimes during resizes, and we do make sure to recreate the swap chain.
VkResult res = vkQueuePresentKHR(vulkan_->GetGraphicsQueue(), &present);
// TODO: Deal with the VK_SUBOPTIMAL_WSI and VK_ERROR_OUT_OF_DATE_WSI
// return codes
if (res == VK_ERROR_OUT_OF_DATE_KHR) {
// ignore, it'll be fine. this happens sometimes during resizes, and we do make sure to recreate the swap chain.
} else {
assert(res == VK_SUCCESS);
}
} else {
assert(res == VK_SUCCESS);
frameData.skipSwap = false;
}
}
+1
View File
@@ -238,6 +238,7 @@ private:
bool readyForFence = true;
bool readyForRun = false;
bool skipSwap = false;
VKRRunType type = VKRRunType::END;
VkFence fence;
+1 -1
View File
@@ -429,7 +429,7 @@ public:
switch (info) {
case APINAME: return "Vulkan";
case VENDORSTRING: return vulkan_->GetPhysicalDeviceProperties().deviceName;
case VENDOR: return StringFromFormat("%08x", vulkan_->GetPhysicalDeviceProperties().vendorID);
case VENDOR: return VulkanVendorString(vulkan_->GetPhysicalDeviceProperties().vendorID);
case DRIVER: return StringFromFormat("%08x", vulkan_->GetPhysicalDeviceProperties().driverVersion);
case SHADELANGVERSION: return "N/A";;
case APIVERSION:
+2
View File
@@ -158,6 +158,8 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool
static double deadline;
deadline = time_now() + timeout;
Core_UpdateDebugStats(g_Config.bShowDebugStats || g_Config.bLogFrameDrops);
PSP_BeginHostFrame();
coreState = CORE_RUNNING;