Merge branch 'master' into TemporaryHackishBranch

# Conflicts:
#	Core/Compatibility.cpp
#	Core/Compatibility.h
#	Core/Config.cpp
#	Core/Config.h
#	Core/CoreTiming.cpp
#	Core/HLE/sceDisplay.cpp
#	GPU/Common/DrawEngineCommon.h
#	GPU/Common/SplineCommon.cpp
#	GPU/D3D11/DrawEngineD3D11.cpp
#	GPU/D3D11/ShaderManagerD3D11.cpp
#	GPU/Directx9/ShaderManagerDX9.cpp
#	GPU/Directx9/VertexShaderGeneratorDX9.cpp
#	GPU/GLES/DrawEngineGLES.cpp
#	GPU/GPUCommon.cpp
#	GPU/Vulkan/DrawEngineVulkan.cpp
#	UI/CwCheatScreen.cpp
#	UI/EmuScreen.cpp
#	UI/GameSettingsScreen.cpp
#	UI/MainScreen.cpp
#	Windows/GEDebugger/VertexPreview.cpp
#	Windows/MainWindowMenu.cpp
#	Windows/ppsspp.rc
#	Windows/resource.h
#	assets/compat.ini
#	ext/native/thin3d/VulkanRenderManager.cpp
#	libretro/libretro.cpp
This commit is contained in:
LunaMoo committed 2019-02-14 02:50:01 +01:00
commit c46de369bb
339 files changed
+8561 -6198

No files matched your search

+1 -1
View File
@@ -65,7 +65,7 @@ desc.txt
Logs
Memstick
memstick
memstick*
Cheats
/git-version.cpp
+276 -255
View File
@@ -3,9 +3,9 @@ cmake_minimum_required(VERSION 3.6)
project(PPSSPP)
#This is supposed to work but doesn't!
if (NOT ANDROID)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
if(NOT ANDROID)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
enable_language(ASM)
@@ -13,64 +13,60 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
add_definitions(-D__STDC_CONSTANT_MACROS)
if(${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
set(CLANG ON)
message("Clang enabled")
set(CLANG ON)
message("Clang enabled")
endif()
if(FORCED_CPU)
message("Detected CPU (${CMAKE_SYSTEM_PROCESSOR}) overridden as: ${FORCED_CPU}")
set(CMAKE_SYSTEM_PROCESSOR ${FORCED_CPU})
message("Detected CPU (${CMAKE_SYSTEM_PROCESSOR}) overridden as: ${FORCED_CPU}")
set(CMAKE_SYSTEM_PROCESSOR ${FORCED_CPU})
endif()
# Detect CPU from CMAKE configuration. Toolchains should set this up
if(CMAKE_SYSTEM_PROCESSOR)
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^arm")
set(ARM ON)
if(UNIX AND NOT APPLE)
execute_process(COMMAND cat /proc/cpuinfo OUTPUT_VARIABLE OUTSTR)
string(FIND "${OUTSTR}" "ODROID-XU" pos)
if(NOT (pos LESS 0))
add_compile_options(-mfloat-abi=hard -marm -mtune=cortex-a15.cortex-a7 -mcpu=cortex-a15 -fomit-frame-pointer)
set(ARM_NO_VULKAN ON)
endif()
set(ARM_DEVICE ON)
if(UNIX AND NOT APPLE)
execute_process(COMMAND cat /proc/cpuinfo OUTPUT_VARIABLE OUTSTR)
string(FIND "${OUTSTR}" "ODROID-XU" pos)
if(NOT (pos LESS 0))
add_compile_options(-mfloat-abi=hard -marm -mtune=cortex-a15.cortex-a7 -mcpu=cortex-a15 -fomit-frame-pointer)
set(ARM_NO_VULKAN ON)
endif()
endif()
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^armv7")
set(ARMV7 ON)
set(ARMV7_DEVICE ON)
add_compile_options(-mfpu=neon)
# Horrifying workaround for bug in android cmake stuff for asm files
if (ANDROID)
if(ANDROID)
set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -target armv7a-none-linux-android")
endif()
endif()
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^aarch64")
set(ARM64 ON)
add_definitions(-DARM64)
set(ARM64 ON)
add_definitions(-DARM64)
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^amd64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^AMD64")
set(X86 ON)
set(X86_64 ON)
set(X86_DEVICE ON)
set(X86_64_DEVICE ON)
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^x86" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i.86")
set(X86 ON)
set(X86_DEVICE ON)
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "^mips")
set(MIPS ON)
set(MIPS_DEVICE ON)
else()
message("Unknown CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
message("Unknown CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}")
endif()
endif()
include(ccache)
# Remove soon?
set(USE_FFMPEG ON)
# the libraries in the ffmpeg/ directory are not compatible with mingw
if(MINGW AND NOT DEFINED USE_SYSTEM_FFMPEG)
set(USE_SYSTEM_FFMPEG ON)
endif()
if(NOT ANDROID AND NOT IOS)
if(ARM OR SIMULATOR)
if(ARM_DEVICE OR SIMULATOR)
set(USING_EGL ON)
endif()
endif()
@@ -93,10 +89,6 @@ if(ANDROID OR WIN32 OR (UNIX AND NOT APPLE AND NOT ARM_NO_VULKAN))
set(VULKAN ON)
endif()
if(NOT DEFINED HEADLESS)
set(HEADLESS OFF)
endif()
if(GOLD)
add_definitions(-DGOLD)
message("Gold Build")
@@ -104,24 +96,19 @@ else()
message("Normal Build")
endif()
# Doesn't link on some platforms
#if(NOT DEFINED UNITTEST)
# set(UNITTEST OFF)
#endif()
# User-editable options (go into CMakeCache.txt)
# :: Processors
option(ARMV7 "Set to ON if targeting an ARMv7 processor" ${ARMV7})
option(ARM "Set to ON if targeting an ARM processor" ${ARM})
option(MIPS "Set to ON if targeting a MIPS processor" ${MIPS})
option(X86 "Set to ON if targeting an X86 processor" ${X86})
option(X86_64 "Set to ON if targeting an X86_64 processor" ${X86_64})
option(ARMV7 "Set to ON if targeting an ARMv7 processor" ${ARMV7_DEVICE})
option(ARM "Set to ON if targeting an ARM processor" ${ARM_DEVICE})
option(MIPS "Set to ON if targeting a MIPS processor" ${MIPS_DEVICE})
option(X86 "Set to ON if targeting an X86 processor" ${X86_DEVICE})
option(X86_64 "Set to ON if targeting an X86_64 processor" ${X86_64_DEVICE})
# :: Environments
option(USING_EGL "Set to ON if target environment uses EGL" ${USING_EGL})
option(USING_FBDEV "Set to ON if target environment uses fbdev (eg. Pandora)" ${USING_FBDEV})
option(USING_GLES2 "Set to ON if target device uses OpenGL ES 2.0" ${USING_GLES2})
option(RASPBIAN "Set to ON to workaround threading issues when building for ARMV7 on Raspbian" ${RASPBIAN})
option(USING_X11_VULKAN "Set to OFF if target environment doesn't use X11 for Vulkan" ON)
option(USE_WAYLAND_WSI "Enable or disable Wayland WSI support for Vulkan" ON)
# :: Frontends
option(USING_QT_UI "Set to ON if you wish to use the Qt frontend wrapper" ${USING_QT_UI})
option(MOBILE_DEVICE "Set to ON when targeting a mobile device" ${MOBILE_DEVICE})
@@ -130,11 +117,11 @@ option(UNITTEST "Set to ON to generate the unittest target" ${UNITTEST})
option(SIMULATOR "Set to ON when targeting an x86 simulator of an ARM platform" ${SIMULATOR})
option(LIBRETRO "Set to ON to generate the libretro target" OFF)
# :: Options
option(USE_FFMPEG "Build with FFMPEG support" ${USE_FFMPEG})
option(USE_FFMPEG "Build with FFMPEG support" ON)
option(USE_DISCORD "Build with Discord support" ON)
option(USE_SYSTEM_SNAPPY "Dynamically link against system snappy" ${USE_SYSTEM_SNAPPY})
option(USE_SYSTEM_FFMPEG "Dynamically link against system FFMPEG" ${USE_SYSTEM_FFMPEG})
option(USE_SYSTEM_LIBZIP "Dynamically link against system libzip" ${USE_SYSTEM_LIBZIP})
option(USE_WAYLAND_WSI "Set to ON to require Wayland support for Vulkan" ${USE_WAYLAND_WSI})
option(USE_ADDRESS_SANITIZER "Use Clang memory sanitizer" ${USE_ADDRESS_SANITIZER})
if(UNIX AND NOT (APPLE OR ANDROID) AND VULKAN)
@@ -145,13 +132,14 @@ if(UNIX AND NOT (APPLE OR ANDROID) AND VULKAN)
message("NOT using X11 for Vulkan")
endif()
# add_definitions(-DVK_USE_PLATFORM_XCB_KHR)
find_package(Wayland)
if (USE_WAYLAND_WSI AND NOT WAYLAND_FOUND)
message(FATAL_ERROR "Could not find libwayland, but USE_WAYLAND_WSI was enabled. Failing.")
endif()
if (WAYLAND_FOUND)
include_directories(${WAYLAND_INCLUDE_DIR})
add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR)
if(USE_WAYLAND_WSI)
find_package(Wayland)
if(NOT WAYLAND_FOUND)
message(STATUS "Could not find Wayland libraries, disabling Wayland WSI support for Vulkan.")
else()
include_directories(${WAYLAND_INCLUDE_DIR})
add_definitions(-DVK_USE_PLATFORM_WAYLAND_KHR)
endif()
endif()
endif()
@@ -182,6 +170,10 @@ if(NOT OPENGL_LIBRARIES AND USING_GLES2)
set(OPENGL_LIBRARIES GLESv2 EGL)
endif()
if(NOT OPENGL_LIBRARIES)
find_package(OpenGL REQUIRED)
endif()
if(USING_EGL)
if(NOT EGL_LIBRARIES)
set(EGL_LIBRARIES EGL)
@@ -189,10 +181,6 @@ if(USING_EGL)
set(OPENGL_LIBRARIES ${OPENGL_LIBRARIES} ${EGL_LIBRARIES})
endif()
if(NOT OPENGL_LIBRARIES)
find_package(OpenGL REQUIRED)
endif()
find_package(SDL2)
include(FindThreads)
@@ -215,7 +203,7 @@ if(MOBILE_DEVICE)
add_definitions(-DMOBILE_DEVICE)
endif()
if (NOT CMAKE_BUILD_TYPE)
if(NOT CMAKE_BUILD_TYPE)
message(STATUS "No build type selected, default to Release")
set(CMAKE_BUILD_TYPE "Release")
endif()
@@ -245,10 +233,10 @@ if(ARM64)
message("Generating for ARMv8, ${CMAKE_BUILD_TYPE}")
endif()
if(NOT MSVC)
if (ANDROID)
if(ANDROID)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
endif()
if (CLANG)
if(CLANG)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch -Wno-uninitialized")
endif()
@@ -280,7 +268,7 @@ if(NOT MSVC)
# Don't compile with strict aliasing, we're not 100% aliasing-safe
add_compile_options(-fno-strict-aliasing)
if (${CMAKE_C_COMPILER_ID} STREQUAL "Intel")
if(${CMAKE_C_COMPILER_ID} STREQUAL "Intel")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -parallel -fopenmp")
else()
add_compile_options(-ffast-math)
@@ -304,7 +292,7 @@ if(NOT MSVC)
set(CMAKE_XCODE_ATTRIBUTE_CLANG_CXX_LIBRARY "libc++")
elseif(NOT ANDROID)
# TODO: See if we can get rid of no-psabi
if (NOT ${CMAKE_C_COMPILER_ID} STREQUAL "Intel" AND NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
if(NOT ${CMAKE_C_COMPILER_ID} STREQUAL "Intel" AND NOT ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
add_definitions(-Wno-psabi)
endif()
add_definitions(-D_XOPEN_SOURCE=700)
@@ -359,14 +347,16 @@ set(CommonX86
Common/x64Analyzer.cpp
Common/x64Analyzer.h
Common/x64Emitter.cpp
Common/x64Emitter.h)
Common/x64Emitter.h
)
source_group(x86 FILES ${CommonX86})
set(CommonARM
Common/ArmCPUDetect.cpp
Common/ArmEmitter.h
Common/ArmEmitter.cpp
Common/ColorConvNEON.cpp)
Common/ColorConvNEON.cpp
)
source_group(ARM FILES ${CommonARM})
set(CommonARM64
@@ -374,30 +364,32 @@ set(CommonARM64
Common/Arm64Emitter.cpp
Common/ArmEmitter.h
Common/ArmEmitter.cpp
Core/Util/DisArm64.cpp)
Core/Util/DisArm64.cpp
)
source_group(ARM64 FILES ${CommonARM64})
set(CommonMIPS
Common/MipsCPUDetect.cpp
Common/MipsEmitter.cpp
Common/MipsEmitter.h)
Common/MipsEmitter.h
)
source_group(MIPS FILES ${CommonMIPS})
if(NOT (X86 OR ARM OR MIPS))
set(CommonFake
Common/FakeCPUDetect.cpp
Common/FakeEmitter.h)
Common/FakeEmitter.h
)
source_group(Fake FILES ${CommonFake})
endif()
set(CommonWindows
Common/stdafx.cpp
Common/stdafx.h)
Common/stdafx.h
)
source_group(Windows FILES ${CommonWindows})
set(CommonVulkan ${CommonExtra}
Common/Vulkan/SPIRVDisasm.cpp
Common/Vulkan/SPIRVDisasm.h
Common/Vulkan/VulkanContext.cpp
Common/Vulkan/VulkanContext.h
Common/Vulkan/VulkanDebug.cpp
@@ -407,7 +399,8 @@ set(CommonVulkan ${CommonExtra}
Common/Vulkan/VulkanLoader.cpp
Common/Vulkan/VulkanLoader.h
Common/Vulkan/VulkanMemory.cpp
Common/Vulkan/VulkanMemory.h)
Common/Vulkan/VulkanMemory.h
)
add_library(Common STATIC
${CommonX86}
@@ -454,7 +447,8 @@ add_library(Common STATIC
Common/ThreadPools.h
Common/ThreadSafeList.h
Common/Timer.cpp
Common/Timer.h)
Common/Timer.h
)
add_subdirectory(ext)
@@ -480,7 +474,7 @@ if(TARGET SDL2::SDL2)
target_link_libraries(Common SDL2::SDL2)
endif()
if(USING_GLES2)
if(USING_GLES2 OR (USING_EGL AND NOT USING_FBDEV))
find_package(X11)
endif()
@@ -491,56 +485,57 @@ add_library(gason STATIC
add_library(rg_etc1 STATIC
ext/native/ext/rg_etc1/rg_etc1.cpp
ext/native/ext/rg_etc1/rg_etc1.h)
ext/native/ext/rg_etc1/rg_etc1.h
)
include_directories(ext/native/ext/rg_etc1)
if(USE_FFMPEG)
if(NOT FFMPEG_DIR)
if(NOT USE_SYSTEM_FFMPEG)
if(ANDROID)
if(ARMV7)
set(PLATFORM_ARCH "android/armv7")
elseif(ARM64)
set(PLATFORM_ARCH "android/arm64")
elseif(X86_64)
set(PLATFORM_ARCH "android/x86_64")
elseif(X86)
set(PLATFORM_ARCH "android/x86")
endif()
elseif(IOS)
set(PLATFORM_ARCH "ios/universal")
elseif(MACOSX)
set(PLATFORM_ARCH "macosx/x86_64")
elseif(LINUX)
if(ARMV7)
set(PLATFORM_ARCH "linux/armv7")
elseif(ARM64)
set(PLATFORM_ARCH "linux/aarch64")
elseif(ARM)
set(PLATFORM_ARCH "linux/arm")
elseif(MIPS)
set(PLATFORM_ARCH "linux/mips32")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(PLATFORM_ARCH "linux/x86_64")
elseif(X86)
set(PLATFORM_ARCH "linux/x86")
endif()
elseif(WIN32)
if(X86_64)
set(PLATFORM_ARCH "Windows/x86_64")
elseif(X86)
set(PLATFORM_ARCH "Windows/x86")
endif()
endif()
if(PLATFORM_ARCH)
set(FFMPEG_DIR "ffmpeg/${PLATFORM_ARCH}")
else()
message("Couldn't find an internal FFmpeg build, using system FFmpeg instead")
endif()
endif()
endif()
if(NOT FFMPEG_DIR)
if(NOT USE_SYSTEM_FFMPEG)
if(ANDROID)
if(ARMV7)
set(PLATFORM_ARCH "android/armv7")
elseif(ARM64)
set(PLATFORM_ARCH "android/arm64")
elseif(X86_64)
set(PLATFORM_ARCH "android/x86_64")
elseif(X86)
set(PLATFORM_ARCH "android/x86")
endif()
elseif(IOS)
set(PLATFORM_ARCH "ios/universal")
elseif(MACOSX)
set(PLATFORM_ARCH "macosx/x86_64")
elseif(LINUX)
if(ARMV7)
set(PLATFORM_ARCH "linux/armv7")
elseif(ARM64)
set(PLATFORM_ARCH "linux/aarch64")
elseif(ARM)
set(PLATFORM_ARCH "linux/arm")
elseif(MIPS)
set(PLATFORM_ARCH "linux/mips32")
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
set(PLATFORM_ARCH "linux/x86_64")
elseif(X86)
set(PLATFORM_ARCH "linux/x86")
endif()
elseif(WIN32)
if(X86_64)
set(PLATFORM_ARCH "Windows/x86_64")
elseif(X86)
set(PLATFORM_ARCH "Windows/x86")
endif()
endif()
if(PLATFORM_ARCH)
set(FFMPEG_DIR "ffmpeg/${PLATFORM_ARCH}")
else()
message("Couldn't find an internal FFmpeg build, using system FFmpeg instead")
endif()
endif()
endif()
find_package(FFmpeg REQUIRED avcodec avformat avutil swresample swscale)
find_package(FFmpeg REQUIRED avcodec avformat avutil swresample swscale)
endif(USE_FFMPEG)
find_package(ZLIB)
@@ -588,7 +583,7 @@ add_library(cityhash STATIC
)
include_directories(ext/cityhash)
if (NOT MSVC)
if(NOT MSVC)
# These can be fast even for debug.
set_target_properties(udis86 PROPERTIES COMPILE_FLAGS "-O3")
set_target_properties(cityhash PROPERTIES COMPILE_FLAGS "-O3")
@@ -657,7 +652,8 @@ else()
ext/native/ext/libzip/zip_unchange.c
ext/native/ext/libzip/zip_unchange_all.c
ext/native/ext/libzip/zip_unchange_archive.c
ext/native/ext/libzip/zip_unchange_data.c)
ext/native/ext/libzip/zip_unchange_data.c
)
target_link_libraries(libzip)
include_directories(ext/native/ext/libzip)
set(LIBZIP_LIBRARY libzip)
@@ -668,15 +664,15 @@ find_path(PNG_PNG_INCLUDE_DIR NAMES "libpng17/png.h")
find_library(PNG_LIBRARY NAMES png17 libpng17)
find_package(PackageHandleStandardArgs)
find_package_handle_standard_args(PNG REQUIRED_VARS PNG_LIBRARY PNG_PNG_INCLUDE_DIR)
if (PNG_FOUND)
if(PNG_FOUND)
include_directories(${PNG_PNG_INCLUDE_DIR})
else()
if(ARM)
set(PNG_ARM_INCLUDES
ext/native/ext/libpng17/arm/arm_init.c
ext/native/ext/libpng17/arm/filter_neon.S
ext/native/ext/libpng17/arm/filter_neon_intrinsics.c
)
ext/native/ext/libpng17/arm/arm_init.c
ext/native/ext/libpng17/arm/filter_neon.S
ext/native/ext/libpng17/arm/filter_neon_intrinsics.c
)
endif()
add_library(png17 STATIC
ext/native/ext/libpng17/pngconf.h
@@ -701,7 +697,8 @@ else()
ext/native/ext/libpng17/pngwrite.c
ext/native/ext/libpng17/pngwtran.c
ext/native/ext/libpng17/pngwutil.c
${PNG_ARM_INCLUDES} )
${PNG_ARM_INCLUDES}
)
set(PNG_LIBRARY png17)
include_directories(ext/native/ext)
endif()
@@ -710,13 +707,14 @@ set(nativeExtra)
set(nativeExtraLibs)
if(ANDROID)
set(nativeExtra ${nativeExtra}
Common/GL/GLInterface/EGLAndroid.cpp
Common/GL/GLInterface/EGLAndroid.h
Common/GL/GLInterface/EGL.cpp
Common/GL/GLInterface/EGL.h
Common/GL/GLInterface/GLInterface.cpp
Common/GL/GLInterfaceBase.h)
set(nativeExtra ${nativeExtra}
Common/GL/GLInterface/EGLAndroid.cpp
Common/GL/GLInterface/EGLAndroid.h
Common/GL/GLInterface/EGL.cpp
Common/GL/GLInterface/EGL.h
Common/GL/GLInterface/GLInterface.cpp
Common/GL/GLInterfaceBase.h
)
set(nativeExtra ${nativeExtra}
ext/native/base/NativeApp.h
@@ -731,7 +729,8 @@ if(ANDROID)
android/jni/native_audio.cpp
android/jni/native_audio.h
android/jni/native-audio-so.cpp
android/jni/native-audio-so.h)
android/jni/native-audio-so.h
)
# No target
elseif(IOS)
set(nativeExtra ${nativeExtra}
@@ -750,7 +749,8 @@ elseif(IOS)
ios/SubtleVolume.mm
ios/iCade/iCadeReaderView.h
ios/iCade/iCadeReaderView.m
ios/iCade/iCadeState.h)
ios/iCade/iCadeState.h
)
set(nativeExtraLibs ${nativeExtraLibs} "-framework Foundation -framework MediaPlayer -framework AudioToolbox -framework CoreGraphics -framework QuartzCore -framework UIKit -framework GLKit -framework OpenAL -framework AVFoundation")
if(EXISTS "${CMAKE_IOS_SDK_ROOT}/System/Library/Frameworks/GameController.framework")
set(nativeExtraLibs ${nativeExtraLibs} "-weak_framework GameController")
@@ -770,34 +770,38 @@ elseif(IOS)
set(TargetBin PPSSPP)
elseif(USING_QT_UI)
set(CMAKE_AUTOMOC ON)
find_package(Qt5 COMPONENTS OpenGL Gui Core)
if(NOT SDL2_FOUND)
find_package(Qt5 COMPONENTS Multimedia)
endif(NOT SDL2_FOUND)
list(APPEND NativeAppSource
Qt/QtMain.cpp
Qt/QtMain.h
Qt/QtHost.cpp
Qt/QtHost.h
Qt/mainwindow.cpp
Qt/mainwindow.h
)
add_definitions(-DUSING_QT_UI)
include_directories(${CMAKE_CURRENT_BINARY_DIR} Qt)
set(CMAKE_AUTOMOC ON)
find_package(Qt5 COMPONENTS OpenGL Gui Core)
if(NOT SDL2_FOUND)
find_package(Qt5 COMPONENTS Multimedia)
endif(NOT SDL2_FOUND)
list(APPEND NativeAppSource
Qt/QtMain.cpp
Qt/QtMain.h
Qt/QtHost.cpp
Qt/QtHost.h
Qt/mainwindow.cpp
Qt/mainwindow.h
)
add_definitions(-DUSING_QT_UI)
if(USING_GLES2)
add_definitions(-DQT_OPENGL_ES -DQT_OPENGL_ES_2)
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR} Qt)
set(nativeExtraLibs ${nativeExtraLibs} Qt5::OpenGL Qt5::Gui Qt5::Core)
set(TargetBin PPSSPPQt)
# Enable SDL if found
if (SDL2_FOUND)
add_definitions(-DSDL)
set(nativeExtra ${nativeExtra}
SDL/SDLJoystick.h
SDL/SDLJoystick.cpp)
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
else(SDL2_FOUND)
set(nativeExtraLibs ${nativeExtraLibs} Qt5::Multimedia)
endif()
# Enable SDL if found
if(SDL2_FOUND)
add_definitions(-DSDL)
set(nativeExtra ${nativeExtra}
SDL/SDLJoystick.h
SDL/SDLJoystick.cpp
)
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
else(SDL2_FOUND)
set(nativeExtraLibs ${nativeExtraLibs} Qt5::Multimedia)
endif()
elseif(WIN32)
# Don't care about SDL.
@@ -807,25 +811,26 @@ elseif(WIN32)
else()
link_directories(dx9sdk/Lib/x86)
endif()
set(nativeExtra ${nativeExtra} ext/native/base/logging.cpp)
set(nativeExtra ${nativeExtra} ext/native/base/logging.cpp)
elseif(TARGET SDL2::SDL2)
set(TargetBin PPSSPPSDL)
# Require SDL
add_definitions(-DSDL)
set(nativeExtra ${nativeExtra}
SDL/SDLJoystick.h
SDL/SDLJoystick.cpp
SDL/SDLMain.cpp
SDL/SDLGLGraphicsContext.cpp
SDL/SDLVulkanGraphicsContext.cpp)
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
if(APPLE)
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm)
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY})
elseif(USING_EGL)
set(nativeExtraLibs ${nativeExtraLibs} pthread)
endif()
set(TargetBin PPSSPPSDL)
set(TargetBin PPSSPPSDL)
# Require SDL
add_definitions(-DSDL)
set(nativeExtra ${nativeExtra}
SDL/SDLJoystick.h
SDL/SDLJoystick.cpp
SDL/SDLMain.cpp
SDL/SDLGLGraphicsContext.cpp
SDL/SDLVulkanGraphicsContext.cpp
)
set(nativeExtraLibs ${nativeExtraLibs} SDL2::SDL2)
if(APPLE)
set(nativeExtra ${nativeExtra} SDL/SDLMain.h SDL/SDLMain.mm)
set(nativeExtraLibs ${nativeExtraLibs} ${COCOA_LIBRARY})
elseif(USING_EGL)
set(nativeExtraLibs ${nativeExtraLibs} pthread)
endif()
set(TargetBin PPSSPPSDL)
else()
message(FATAL_ERROR "Could not find SDL2. Failing.")
endif()
@@ -845,6 +850,7 @@ list(APPEND NativeAppSource
UI/PauseScreen.cpp
UI/GameScreen.cpp
UI/GameSettingsScreen.cpp
UI/GPUDriverTestScreen.cpp
UI/TiltAnalogSettingsScreen.cpp
UI/TiltEventProcessor.cpp
UI/TouchControlLayoutScreen.cpp
@@ -861,12 +867,13 @@ list(APPEND NativeAppSource
UI/ProfilerDraw.cpp
UI/ui_atlas.cpp
UI/TextureUtil.cpp
UI/ComboKeyMappingScreen.cpp)
UI/ComboKeyMappingScreen.cpp
)
if(ANDROID)
if (ARM)
if(ARM)
set(NativeAppSource ${NativeAppSource} android/jni/ArmEmitterTest.cpp)
elseif (ARM64)
elseif(ARM64)
set(NativeAppSource ${NativeAppSource} android/jni/Arm64EmitterTest.cpp)
endif()
set(nativeExtra ${nativeExtra} ${NativeAppSource})
@@ -878,7 +885,8 @@ set(THIN3D_PLATFORMS ext/native/thin3d/thin3d_gl.cpp
ext/native/thin3d/GLQueueRunner.cpp
ext/native/thin3d/GLQueueRunner.h
ext/native/thin3d/DataFormatGL.cpp
ext/native/thin3d/DataFormatGL.h)
ext/native/thin3d/DataFormatGL.h
)
set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS}
ext/native/thin3d/thin3d_vulkan.cpp
@@ -886,16 +894,18 @@ set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS}
ext/native/thin3d/VulkanRenderManager.h
ext/native/thin3d/VulkanQueueRunner.cpp
ext/native/thin3d/VulkanQueueRunner.h
ext/native/thin3d/DataFormat.h)
ext/native/thin3d/DataFormat.h
)
if(WIN32)
set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS}
ext/native/thin3d/thin3d_d3d9.cpp
ext/native/thin3d/thin3d_d3d11.cpp
ext/native/thin3d/d3dx9_loader.cpp
ext/native/thin3d/d3dx9_loader.h
ext/native/thin3d/d3d11_loader.cpp
ext/native/thin3d/d3d11_loader.h)
set(THIN3D_PLATFORMS ${THIN3D_PLATFORMS}
ext/native/thin3d/thin3d_d3d9.cpp
ext/native/thin3d/thin3d_d3d11.cpp
ext/native/thin3d/d3dx9_loader.cpp
ext/native/thin3d/d3dx9_loader.h
ext/native/thin3d/d3d11_loader.cpp
ext/native/thin3d/d3d11_loader.h
)
endif()
add_library(native STATIC
@@ -1052,21 +1062,22 @@ add_library(native STATIC
ext/native/ext/jpge/jpgd.cpp
ext/native/ext/jpge/jpgd.h
ext/native/ext/jpge/jpge.cpp
ext/native/ext/jpge/jpge.h)
ext/native/ext/jpge/jpge.h
)
include_directories(ext/native)
if (LINUX AND NOT ANDROID)
SET(RT_LIB rt)
if(LINUX AND NOT ANDROID)
set(RT_LIB rt)
endif()
SET(ATOMIC_LIB)
set(ATOMIC_LIB)
if(ANDROID)
SET(ATOMIC_LIB atomic)
set(ATOMIC_LIB atomic)
endif()
target_link_libraries(native ${LIBZIP_LIBRARY} ${PNG_LIBRARY} ${ZLIB_LIBRARY} rg_etc1 gason udis86 ${RT_LIB} ${nativeExtraLibs} ${ATOMIC_LIB})
if(TARGET Ext::GLEW)
target_link_libraries(native Ext::GLEW)
target_link_libraries(native Ext::GLEW)
endif()
if(ANDROID)
@@ -1088,7 +1099,8 @@ add_library(kirk STATIC
ext/libkirk/bn.c
ext/libkirk/ec.c
ext/libkirk/kirk_engine.c
ext/libkirk/kirk_engine.h)
ext/libkirk/kirk_engine.h
)
include_directories(ext/libkirk)
add_library(sfmt19937 STATIC
@@ -1133,7 +1145,7 @@ set(CoreExtra ${CoreExtra}
Core/MIPS/IR/IRPassSimplify.h
Core/MIPS/IR/IRRegCache.cpp
Core/MIPS/IR/IRRegCache.h
)
)
list(APPEND CoreExtra
Core/MIPS/ARM/ArmAsm.cpp
@@ -1169,7 +1181,8 @@ list(APPEND CoreExtra
Core/MIPS/ARM64/Arm64RegCacheFPU.cpp
Core/MIPS/ARM64/Arm64RegCacheFPU.h
GPU/Common/VertexDecoderArm64.cpp
Core/Util/DisArm64.cpp)
Core/Util/DisArm64.cpp
)
list(APPEND CoreExtra
Core/MIPS/x86/Asm.cpp
@@ -1197,17 +1210,19 @@ list(APPEND CoreExtra
GPU/Common/VertexDecoderFake.cpp
)
if (NOT MOBILE_DEVICE)
if(NOT MOBILE_DEVICE)
set(CoreExtra ${CoreExtra}
Core/AVIDump.cpp
Core/AVIDump.h
Core/WaveFile.cpp
Core/WaveFile.h)
Core/WaveFile.h
)
endif()
set(GPU_GLES
GPU/GLES/DepalettizeShaderGLES.cpp
GPU/GLES/DepalettizeShaderGLES.h
GPU/GLES/DepthBufferGLES.cpp
GPU/GLES/GPU_GLES.cpp
GPU/GLES/GPU_GLES.h
GPU/GLES/FragmentShaderGeneratorGLES.cpp
@@ -1232,7 +1247,7 @@ set(GPU_GLES
)
set(GPU_VULKAN
GPU/Vulkan/DepalettizeShaderVulkan.cpp
GPU/Vulkan/DepalettizeShaderVulkan.cpp
GPU/Vulkan/DepalettizeShaderVulkan.h
GPU/Vulkan/DebugVisVulkan.cpp
GPU/Vulkan/DebugVisVulkan.h
@@ -1262,7 +1277,7 @@ set(GPU_VULKAN
)
set(GPU_D3D9
GPU/Directx9/DepalettizeShaderDX9.cpp
GPU/Directx9/DepalettizeShaderDX9.cpp
GPU/Directx9/DepalettizeShaderDX9.h
GPU/Directx9/DrawEngineDX9.cpp
GPU/Directx9/DrawEngineDX9.h
@@ -1286,7 +1301,7 @@ set(GPU_D3D9
)
set(GPU_D3D11
GPU/D3D11/DepalettizeShaderD3D11.cpp
GPU/D3D11/DepalettizeShaderD3D11.cpp
GPU/D3D11/DepalettizeShaderD3D11.h
GPU/D3D11/DrawEngineD3D11.cpp
GPU/D3D11/DrawEngineD3D11.h
@@ -1395,7 +1410,8 @@ set(GPU_SOURCES
GPU/Software/SoftGpu.h
GPU/Software/TransformUnit.cpp
GPU/Software/TransformUnit.h
GPU/ge_constants.h)
GPU/ge_constants.h
)
# 'ppsspp_jni' on ANDROID, 'Core' everywhere else
# SHARED on ANDROID, STATIC everywhere else
@@ -1733,13 +1749,14 @@ add_library(${CoreLibName} ${CoreLinkType}
${CORE_NEON}
${GPU_SOURCES}
ext/disarm.cpp
git-version.cpp)
git-version.cpp
)
if(ANDROID)
set(CoreExtraLibs ${CoreExtraLibs} android)
if(X86_64)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Bsymbolic")
endif()
set(CoreExtraLibs ${CoreExtraLibs} android)
if(X86_64)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-Bsymbolic")
endif()
endif()
set(CoreExtraLibs ${CoreExtraLibs} armips)
@@ -1753,27 +1770,28 @@ set(CoreExtraLibs ${CoreExtraLibs} armips)
set(GlslangLibs glslang OGLCompiler OSDependent SPIRV SPVRemapper spirv-cross-glsl)
if(WIN32)
set(GlslangLibs ${GlslangLibs} spirv-cross-hlsl)
set(GlslangLibs ${GlslangLibs} spirv-cross-hlsl)
endif()
target_link_libraries(${CoreLibName} Common native kirk cityhash sfmt19937 xbrz xxhash ${GlslangLibs}
${CoreExtraLibs} ${OPENGL_LIBRARIES} ${X11_LIBRARIES} ${CMAKE_DL_LIBS})
if(FFmpeg_FOUND)
target_compile_definitions(${CoreLibName} PRIVATE USE_FFMPEG=1)
target_link_libraries(${CoreLibName}
FFmpeg::avcodec
FFmpeg::avformat
FFmpeg::avutil
FFmpeg::swresample
FFmpeg::swscale
${ZLIB_LIBRARY}
)
target_compile_definitions(${CoreLibName} PRIVATE USE_FFMPEG=1)
target_link_libraries(${CoreLibName}
FFmpeg::avcodec
FFmpeg::avformat
FFmpeg::avutil
FFmpeg::swresample
FFmpeg::swscale
${ZLIB_LIBRARY}
)
endif()
# Discord integration
if(NOT IOS)
target_link_libraries(${CoreLibName} discord-rpc)
if(USE_DISCORD AND NOT IOS)
add_definitions(-DUSE_DISCORD=1)
target_link_libraries(${CoreLibName} discord-rpc)
endif()
setup_target_project(${CoreLibName} Core)
@@ -1885,7 +1903,8 @@ set(WindowsFiles
Windows/ppsspp.rc
Windows/resource.h
Windows/stdafx.cpp
Windows/stdafx.h)
Windows/stdafx.h
)
list(APPEND LinkCommon ${CoreLibName} ${CMAKE_THREAD_LIBS_INIT})
@@ -1908,7 +1927,10 @@ set(NativeAssets
assets/ppge_atlas.zim
assets/rargray.png
assets/unknown.png
assets/zip.png)
assets/zip.png
source_assets/image/logo.png
source_assets/image/icon_regular_72.png
)
if(HEADLESS)
@@ -1919,9 +1941,9 @@ if(HEADLESS)
headless/Compare.cpp
headless/Compare.h
headless/SDLHeadlessHost.cpp
headless/SDLHeadlessHost.h)
target_link_libraries(PPSSPPHeadless
${COCOA_LIBRARY} ${LinkCommon})
headless/SDLHeadlessHost.h
)
target_link_libraries(PPSSPPHeadless ${COCOA_LIBRARY} ${LinkCommon})
setup_target_project(PPSSPPHeadless headless)
endif()
@@ -1936,8 +1958,7 @@ if(UNITTEST)
Core/MIPS/ARM/ArmRegCache.cpp
Core/MIPS/ARM/ArmRegCacheFPU.cpp
)
target_link_libraries(unitTest
${COCOA_LIBRARY} ${LinkCommon} Common)
target_link_libraries(unitTest ${COCOA_LIBRARY} ${LinkCommon} Common)
setup_target_project(unitTest unittest)
endif()
@@ -1945,12 +1966,12 @@ if(LIBRETRO)
add_subdirectory(libretro)
endif()
if (TargetBin)
if (IOS OR APPLE)
if (APPLE AND NOT IOS)
set(ICON_PATH_ABS ${CMAKE_CURRENT_SOURCE_DIR}/icons/ppsspp.icns)
set( MACOSX_BUNDLE_ICON_FILE ppsspp.icns )
set_source_files_properties(${ICON_PATH_ABS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
if(TargetBin)
if(IOS OR APPLE)
if(APPLE AND NOT IOS)
set(ICON_PATH_ABS ${CMAKE_CURRENT_SOURCE_DIR}/icons/ppsspp.icns)
set(MACOSX_BUNDLE_ICON_FILE ppsspp.icns)
set_source_files_properties(${ICON_PATH_ABS} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources")
endif()
# TODO: there must a native way to copy these.
@@ -1960,17 +1981,17 @@ if (TargetBin)
file(GLOB_RECURSE LANG_FILES assets/lang/*)
file(GLOB_RECURSE SHADER_FILES assets/shaders/*)
if (APPLE AND NOT IOS)
set_source_files_properties(${NativeAssets} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets")
set_source_files_properties(${FLASH0_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets/flash0/font")
set_source_files_properties(${LANG_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets/lang")
set_source_files_properties(${SHADER_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets/shaders")
if(APPLE AND NOT IOS)
set_source_files_properties(${NativeAssets} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets")
set_source_files_properties(${FLASH0_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets/flash0/font")
set_source_files_properties(${LANG_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets/lang")
set_source_files_properties(${SHADER_FILES} PROPERTIES MACOSX_PACKAGE_LOCATION "MacOS/assets/shaders")
endif()
if (IOS)
add_executable(${TargetBin} MACOSX_BUNDLE ${ICON_PATH_ABS} ${NativeAssets} ${SHADER_FILES} ${FLASH0_FILES} ${LANG_FILES} ${NativeAppSource} "ios/Launch Screen.storyboard")
if(IOS)
add_executable(${TargetBin} MACOSX_BUNDLE ${ICON_PATH_ABS} ${NativeAssets} ${SHADER_FILES} ${FLASH0_FILES} ${LANG_FILES} ${NativeAppSource} "ios/Launch Screen.storyboard")
else()
add_executable(${TargetBin} MACOSX_BUNDLE ${ICON_PATH_ABS} ${NativeAssets} ${SHADER_FILES} ${FLASH0_FILES} ${LANG_FILES} ${NativeAppSource})
add_executable(${TargetBin} MACOSX_BUNDLE ${ICON_PATH_ABS} ${NativeAssets} ${SHADER_FILES} ${FLASH0_FILES} ${LANG_FILES} ${NativeAppSource})
endif()
elseif(WIN32)
add_executable(${TargetBin} WIN32 ${NativeAppSource})
@@ -1988,8 +2009,8 @@ endif()
# installs
if(NOT ANDROID)
file(INSTALL ${NativeAssets} DESTINATION assets)
file(INSTALL assets/flash0 DESTINATION assets)
file(INSTALL ${NativeAssets} DESTINATION assets)
file(INSTALL assets/flash0 DESTINATION assets)
endif()
# packaging and code signing
if(IOS)
@@ -2000,7 +2021,7 @@ if(IOS)
file(INSTALL ${IOSAssets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/assets)
file(GLOB IOSAssets ios/assets/Default-568h@*.png)
file(INSTALL ${IOSAssets} DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
if (IOS_DEBUG)
if(IOS_DEBUG)
file(INSTALL pspautotests DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/assets)
endif()
set(RSRC_XIB_FILES assets/Icon@2x.png)
@@ -2008,11 +2029,11 @@ if(IOS)
set_source_files_properties(${RSRC_XIB_FILES}
PROPERTIES MACOSX_PACKAGE_LOCATION Resources
)
if(CMAKE_GENERATOR STREQUAL "Xcode")
set(APP_DIR_NAME "$(TARGET_BUILD_DIR)/$(FULL_PRODUCT_NAME)")
else()
set(APP_DIR_NAME "$<TARGET_FILE_DIR:PPSSPP>")
endif()
if(CMAKE_GENERATOR STREQUAL "Xcode")
set(APP_DIR_NAME "$(TARGET_BUILD_DIR)/$(FULL_PRODUCT_NAME)")
else()
set(APP_DIR_NAME "$<TARGET_FILE_DIR:PPSSPP>")
endif()
add_custom_command(TARGET PPSSPP POST_BUILD
COMMAND mkdir -p \"${APP_DIR_NAME}\"
COMMAND tar -c -C ${CMAKE_CURRENT_BINARY_DIR} --exclude .DS_Store --exclude .git assets *.png | tar -x -C \"${APP_DIR_NAME}\"
@@ -2023,8 +2044,8 @@ if(IOS)
RESOURCE "ios/Launch Screen.storyboard"
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET}
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "iPhone/iPad"
XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES
XCODE_ATTRIBUTE_ENABLE_BITCODE NO
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-"
XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES
XCODE_ATTRIBUTE_ENABLE_BITCODE NO
XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY "-"
)
endif()
+3 -3
View File
@@ -80,6 +80,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<MinimalRebuild>false</MinimalRebuild>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -107,6 +108,7 @@
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<MinimalRebuild>false</MinimalRebuild>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
@@ -242,7 +244,6 @@
<ClInclude Include="ThreadSafeList.h" />
<ClInclude Include="Thunk.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="Vulkan\SPIRVDisasm.h" />
<ClInclude Include="Vulkan\VulkanContext.h" />
<ClInclude Include="Vulkan\VulkanDebug.h" />
<ClInclude Include="Vulkan\VulkanImage.h" />
@@ -314,7 +315,6 @@
<ClCompile Include="ThreadPools.cpp" />
<ClCompile Include="Thunk.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="Vulkan\SPIRVDisasm.cpp" />
<ClCompile Include="Vulkan\VulkanContext.cpp" />
<ClCompile Include="Vulkan\VulkanDebug.cpp" />
<ClCompile Include="Vulkan\VulkanImage.cpp" />
@@ -331,4 +331,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>
+1 -7
View File
@@ -58,9 +58,6 @@
</ClInclude>
<ClInclude Include="GraphicsContext.h" />
<ClInclude Include="DbgNew.h" />
<ClInclude Include="Vulkan\SPIRVDisasm.h">
<Filter>Vulkan</Filter>
</ClInclude>
<ClInclude Include="Vulkan\VulkanLoader.h">
<Filter>Vulkan</Filter>
</ClInclude>
@@ -119,9 +116,6 @@
<ClCompile Include="GL\GLInterface\GLInterface.cpp">
<Filter>GL\GLInterface</Filter>
</ClCompile>
<ClCompile Include="Vulkan\SPIRVDisasm.cpp">
<Filter>Vulkan</Filter>
</ClCompile>
<ClCompile Include="Vulkan\VulkanLoader.cpp">
<Filter>Vulkan</Filter>
</ClCompile>
@@ -155,4 +149,4 @@
<UniqueIdentifier>{c14d66ef-5f7c-4565-975a-72774e7ccfb9}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>
+18 -16
View File
@@ -30,6 +30,7 @@
#ifdef _WIN32
#include "CommonWindows.h"
#include <Windows.h>
#include <shlobj.h> // for SHGetFolderPath
#include <shellapi.h>
#include <commdlg.h> // for GetSaveFileName
@@ -121,7 +122,11 @@ std::string ResolvePath(const std::string &path) {
std::wstring input = ConvertUTF8ToWString(path);
if (getFinalPathNameByHandleW) {
#if PPSSPP_PLATFORM(UWP)
HANDLE hFile = CreateFile2(input.c_str(), GENERIC_READ, FILE_SHARE_READ, OPEN_EXISTING, nullptr);
#else
HANDLE hFile = CreateFile(input.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, nullptr);
#endif
if (hFile == INVALID_HANDLE_VALUE) {
wcscpy_s(buf, BUF_SIZE - 1, input.c_str());
} else {
@@ -336,7 +341,7 @@ bool CreateFullPath(const std::string &path)
return true;
}
std::string subPath = fullPath.substr(0, position);
if (!File::Exists(subPath))
if (position != 0 && !File::Exists(subPath))
File::CreateDir(subPath);
// A safety check
@@ -647,7 +652,6 @@ bool DeleteDirRecursively(const std::string &directory)
if (hFind == INVALID_HANDLE_VALUE)
{
FindClose(hFind);
return false;
}
@@ -656,17 +660,16 @@ bool DeleteDirRecursively(const std::string &directory)
{
const std::string virtualName = ConvertWStringToUTF8(ffd.cFileName);
#else
struct dirent dirent, *result = NULL;
struct dirent *result = NULL;
DIR *dirp = opendir(directory.c_str());
if (!dirp)
return false;
// non windows loop
while (!readdir_r(dirp, &dirent, &result) && result)
while ((result = readdir(dirp)))
{
const std::string virtualName = result->d_name;
#endif
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
@@ -678,10 +681,11 @@ bool DeleteDirRecursively(const std::string &directory)
{
if (!DeleteDirRecursively(newPath))
{
#ifndef _WIN32
#ifndef _WIN32
closedir(dirp);
#endif
#else
FindClose(hFind);
#endif
return false;
}
}
@@ -689,10 +693,11 @@ bool DeleteDirRecursively(const std::string &directory)
{
if (!File::Delete(newPath))
{
#ifndef _WIN32
#ifndef _WIN32
closedir(dirp);
#endif
#else
FindClose(hFind);
#endif
return false;
}
}
@@ -704,8 +709,7 @@ bool DeleteDirRecursively(const std::string &directory)
}
closedir(dirp);
#endif
File::DeleteDir(directory);
return true;
return File::DeleteDir(directory);
#endif
}
@@ -718,13 +722,11 @@ void CopyDir(const std::string &source_path, const std::string &dest_path)
if (!File::Exists(source_path)) return;
if (!File::Exists(dest_path)) File::CreateFullPath(dest_path);
struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; };
struct dirent_large diren;
struct dirent *result = NULL;
DIR *dirp = opendir(source_path.c_str());
if (!dirp) return;
while (!readdir_r(dirp, (dirent*) &diren, &result) && result)
while ((result = readdir(dirp)))
{
const std::string virtualName(result->d_name);
// check for "." and ".."
+1
View File
@@ -7,6 +7,7 @@
#endif
#include <cstdint>
#include <vector>
#include "OSVersion.h"
#include "Common/CommonWindows.h"
+17 -1
View File
@@ -95,4 +95,20 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
*_pExtension = full_path.substr(fname_end);
return true;
}
}
std::string GetFilenameFromPath(std::string full_path) {
size_t pos;
#ifdef _WIN32
pos = full_path.rfind('\\');
if (pos != std::string::npos) {
return full_path.substr(pos + 1);
}
#endif
pos = full_path.rfind('/');
if (pos != std::string::npos) {
return full_path.substr(pos + 1);
}
// No directory components, just return the full path.
return full_path;
}
+2
View File
@@ -45,3 +45,5 @@ inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension);
std::string GetFilenameFromPath(std::string full_path);
-617
View File
@@ -1,617 +0,0 @@
#include <sstream>
#include "Common/StringUtils.h"
#include "Common/Vulkan/SPIRVDisasm.h"
#include "ext/vulkan/spirv.hpp"
#define WRITE p+=sprintf
struct SpirvID {
std::string name;
int opcode;
};
struct OpInfo {
const char *name;
const char *extra;
};
static const char *executionModelNames[] = {
"Vertex", // 0,
"TessellationControl", // 1,
"TessellationEvaluation", // 2,
"Geometry", // 3,
"Fragment", // 4,
"GLCompute", // 5,
"Kernel", // 6,
};
static const char *storageClassNames[] = {
"UniformConstant",
"Input",
"Uniform",
"Output",
"Workgroup",
"CrossWorkgroup",
"Private",
"Function",
"Generic",
"PushConstant",
"AtomicCounter",
"Image",
};
static const char *decorationNames[] = {
"RelaxedPrecision", // 0,
"SpecId", // 1,
"Block", // 2,
"BufferBlock", // 3,
"RowMajor", // 4,
"ColMajor", // 5,
"ArrayStride", // 6,
"MatrixStride", // 7,
"GLSLShared", // 8,
"GLSLPacked", // 9,
"CPacked", // 10,
"BuiltIn", // 11,
nullptr, // 12
"NoPerspective", // 13,
"Flat", // 14,
"Patch", // 15,
"Centroid", // 16,
"Sample", // 17,
"Invariant", // 18,
"Restrict", // 19,
"Aliased", // 20,
"Volatile", // 21,
"Constant", // 22,
"Coherent", // 23,
"NonWritable", // 24,
"NonReadable", // 25,
"Uniform", // 26,
nullptr, // 27
"SaturatedConversion", // 28,
"Stream", // 29,
"Location", // 30,
"Component", // 31,
"Index", // 32,
"Binding", // 33,
"DescriptorSet", // 34,
"Offset", // 35,
"XfbBuffer", // 36,
"XfbStride", // 37,
"FuncParamAttr", // 38,
"FPRoundingMode", // 39,
"FPFastMathMode", // 40,
"LinkageAttributes", // 41,
"NoContraction", // 42,
"InputAttachmentIndex", // 43,
"Alignment", // 44,
};
static const OpInfo opInfo[] = {
{"Nop"}, // 0,
{"Undef"}, // 1,
{"SourceContinued"}, // 2,
{"Source"}, // 3,
{"SourceExtension"}, // 4,
{"Name"}, // 5,
{"MemberName"}, // 6,
{"String"}, // 7,
{"Line"}, // 8,
{nullptr}, // 9
{"Extension"}, // 10,
{"ExtInstImport"}, // 11,
{"ExtInst"}, // 12,
{nullptr}, // 13
{"MemoryModel"}, // 14,
{"EntryPoint"}, // 15,
{"ExecutionMode"}, // 16,
{"Capability"}, // 17,
{nullptr}, // 18
{"TypeVoid"}, // 19,
{"TypeBool"}, // 20,
{"TypeInt"}, // 21,
{"TypeFloat"}, // 22,
{"TypeVector"}, // 23,
{"TypeMatrix"}, // 24,
{"TypeImage"}, // 25,
{"TypeSampler"}, // 26,
{"TypeSampledImage"}, // 27,
{"TypeArray"}, // 28,
{"TypeRuntimeArray"}, // 29,
{"TypeStruct"}, // 30,
{"TypeOpaque"}, // 31,
{"TypePointer"}, // 32,
{"TypeFunction"}, // 33,
{"TypeEvent"}, // 34,
{"TypeDeviceEvent"}, // 35,
{"TypeReserveId"}, // 36,
{"TypeQueue"}, // 37,
{"TypePipe"}, // 38,
{"TypeForwardPointer"}, // 39,
{nullptr}, // 40
{"ConstantTrue"}, // 41,
{"ConstantFalse"}, // 42,
{"Constant"}, // 43,
{"ConstantComposite"}, // 44,
{"ConstantSampler"}, // 45,
{"ConstantNull"}, // 46,
{nullptr}, // 47
{"SpecConstantTrue"}, // 48,
{"SpecConstantFalse"}, // 49,
{"SpecConstant"}, // 50,
{"SpecConstantComposite"}, // 51,
{"SpecConstantOp"}, // 52,
{nullptr}, // 53
{"Function"}, // 54,
{"FunctionParameter"}, // 55,
{"FunctionEnd"}, // 56,
{"FunctionCall"}, // 57,
{nullptr}, // 58
{"Variable"}, // 59,
{"ImageTexelPointer"}, // 60,
{"Load"}, // 61,
{"Store"}, // 62,
{"CopyMemory"}, // 63,
{"CopyMemorySized"}, // 64,
{"AccessChain"}, // 65,
{"InBoundsAccessChain"}, // 66,
{"PtrAccessChain"}, // 67,
{"ArrayLength"}, // 68,
{"GenericPtrMemSemantics"}, // 69,
{"InBoundsPtrAccessChain"}, // 70,
{"Decorate"}, // 71,
{"MemberDecorate"}, // 72,
{"DecorationGroup"}, // 73,
{"GroupDecorate"}, // 74,
{"GroupMemberDecorate"}, // 75,
{nullptr}, // 76
{"VectorExtractDynamic"}, // 77,
{"VectorInsertDynamic"}, // 78,
{"VectorShuffle"}, // 79,
{"CompositeConstruct"}, // 80,
{"CompositeExtract"}, // 81,
{"CompositeInsert"}, // 82,
{"CopyObject"}, // 83,
{"Transpose"}, // 84,
{nullptr}, // 85
{"SampledImage"}, // 86,
{"ImageSampleImplicitLod"}, // 87,
{"ImageSampleExplicitLod"}, // 88,
{"ImageSampleDrefImplicitLod"}, // 89,
{"ImageSampleDrefExplicitLod"}, // 90,
{"ImageSampleProjImplicitLod"}, // 91,
{"ImageSampleProjExplicitLod"}, // 92,
{"ImageSampleProjDrefImplicitLod"}, // 93,
{"ImageSampleProjDrefExplicitLod"}, // 94,
{"ImageFetch"}, // 95,
{"ImageGather"}, // 96,
{"ImageDrefGather"}, // 97,
{"ImageRead"}, // 98,
{"ImageWrite"}, // 99,
{"Image"}, // 100,
{"ImageQueryFormat"}, // 101,
{"ImageQueryOrder"}, // 102,
{"ImageQuerySizeLod"}, // 103,
{"ImageQuerySize"}, // 104,
{"ImageQueryLod"}, // 105,
{"ImageQueryLevels"}, // 106,
{"ImageQuerySamples"}, // 107,
{nullptr}, // 108
{"ConvertFToU"}, // 109,
{"ConvertFToS"}, // 110,
{"ConvertSToF"}, // 111,
{"ConvertUToF"}, // 112,
{"UConvert"}, // 113,
{"SConvert"}, // 114,
{"FConvert"}, // 115,
{"QuantizeToF16"}, // 116,
{"ConvertPtrToU"}, // 117,
{"SatConvertSToU"}, // 118,
{"SatConvertUToS"}, // 119,
{"ConvertUToPtr"}, // 120,
{"PtrCastToGeneric"}, // 121,
{"GenericCastToPtr"}, // 122,
{"GenericCastToPtrExplicit"}, // 123,
{"Bitcast"}, // 124,
{nullptr}, // 125
{"SNegate"}, // 126,
{"FNegate"}, // 127,
{"IAdd"}, // 128,
{"FAdd", "+"}, // 129,
{"ISub"}, // 130,
{"FSub", "-"}, // 131,
{"IMul"}, // 132,
{"FMul", "*"}, // 133,
{"UDiv"}, // 134,
{"SDiv"}, // 135,
{"FDiv", "/"}, // 136,
{"UMod"}, // 137,
{"SRem"}, // 138,
{"SMod"}, // 139,
{"FRem"}, // 140,
{"FMod", "%"}, // 141,
{"VectorTimesScalar"}, // 142,
{"MatrixTimesScalar"}, // 143,
{"VectorTimesMatrix"}, // 144,
{"MatrixTimesVector"}, // 145,
{"MatrixTimesMatrix"}, // 146,
{"OuterProduct"}, // 147,
{"Dot", " dot "}, // 148,
{"IAddCarry"}, // 149,
{"ISubBorrow"}, // 150,
{"UMulExtended"}, // 151,
{"SMulExtended"}, // 152,
{nullptr}, // 153
{"Any"}, // 154,
{"All"}, // 155,
{"IsNan"}, // 156,
{"IsInf"}, // 157,
{"IsFinite"}, // 158,
{"IsNormal"}, // 159,
{"SignBitSet"}, // 160,
{"LessOrGreater"}, // 161,
{"Ordered"}, // 162,
{"Unordered"}, // 163,
{"LogicalEqual"}, // 164,
{"LogicalNotEqual"}, // 165,
{"LogicalOr"}, // 166,
{"LogicalAnd"}, // 167,
{"LogicalNot"}, // 168,
{"Select"}, // 169,
{"IEqual"}, // 170,
{"INotEqual"}, // 171,
{"UGreaterThan"}, // 172,
{"SGreaterThan"}, // 173,
{"UGreaterThanEqual"}, // 174,
{"SGreaterThanEqual"}, // 175,
{"ULessThan"}, // 176,
{"SLessThan"}, // 177,
{"ULessThanEqual"}, // 178,
{"SLessThanEqual"}, // 179,
{"FOrdEqual", "=="}, // 180,
{"FUnordEqual", "=="}, // 181,
{"FOrdNotEqual", "!="}, // 182,
{"FUnordNotEqual", "!="}, // 183,
{"FOrdLessThan"}, // 184,
{"FUnordLessThan"}, // 185,
{"FOrdGreaterThan"}, // 186,
{"FUnordGreaterThan"}, // 187,
{"FOrdLessThanEqual"}, // 188,
{"FUnordLessThanEqual"}, // 189,
{"FOrdGreaterThanEqual"}, // 190,
{"FUnordGreaterThanEqual"}, // 191,
{ nullptr }, // 192
{ nullptr }, // 193
{"ShiftRightLogical"}, // 194,
{"ShiftRightArithmetic"}, // 195,
{"ShiftLeftLogical"}, // 196,
{"BitwiseOr", "|"}, // 197,
{"BitwiseXor", "^"}, // 198,
{"BitwiseAnd", "&"}, // 199,
{"Not", "~"}, // 200,
{"BitFieldInsert"}, // 201,
{"BitFieldSExtract"}, // 202,
{"BitFieldUExtract"}, // 203,
{"BitReverse"}, // 204,
{"BitCount"}, // 205,
{nullptr},
{"DPdx"}, // 207,
{"DPdy"}, // 208,
{"Fwidth"}, // 209,
{"DPdxFine"}, // 210,
{"DPdyFine"}, // 211,
{"FwidthFine"}, // 212,
{"DPdxCoarse"}, // 213,
{"DPdyCoarse"}, // 214,
{"FwidthCoarse"}, // 215,
{nullptr}, // 216
{nullptr}, // 217
{"EmitVertex"}, // 218,
{"EndPrimitive"}, // 219,
{"EmitStreamVertex"}, // 220,
{"EndStreamPrimitive"}, // 221,
{nullptr}, // 222
{nullptr}, // 223
{"ControlBarrier"}, // 224,
{"MemoryBarrier"}, // 225,
{nullptr}, // 226
{"AtomicLoad"}, // 227,
{"AtomicStore"}, // 228,
{"AtomicExchange"}, // 229,
{"AtomicCompareExchange"}, // 230,
{"AtomicCompareExchangeWeak"}, // 231,
{"AtomicIIncrement"}, // 232,
{"AtomicIDecrement"}, // 233,
{"AtomicIAdd"}, // 234,
{"AtomicISub"}, // 235,
{"AtomicSMin"}, // 236,
{"AtomicUMin"}, // 237,
{"AtomicSMax"}, // 238,
{"AtomicUMax"}, // 239,
{"AtomicAnd"}, // 240,
{"AtomicOr"}, // 241,
{"AtomicXor"}, // 242,
{ nullptr }, // 243,
{ nullptr }, // 244,
{"Phi"}, // 245,
{"LoopMerge"}, // 246,
{"SelectionMerge"}, // 247,
{"Label"}, // 248,
{"Branch"}, // 249,
{"BranchConditional"}, // 250,
{"Switch"}, // 251,
{"Kill"}, // 252,
{"Return"}, // 253,
{"ReturnValue"}, // 254,
{"Unreachable"}, // 255,
{"LifetimeStart"}, // 256,
{"LifetimeStop"}, // 257,
{ nullptr },
{"GroupAsyncCopy"}, // 259,
{"GroupWaitEvents"}, // 260,
{"GroupAll"}, // 261,
{"GroupAny"}, // 262,
{"GroupBroadcast"}, // 263,
{"GroupIAdd"}, // 264,
{"GroupFAdd"}, // 265,
{"GroupFMin"}, // 266,
{"GroupUMin"}, // 267,
{"GroupSMin"}, // 268,
{"GroupFMax"}, // 269,
{"GroupUMax"}, // 270,
{"GroupSMax"}, // 271,
{nullptr}, // 272
{nullptr}, // 273
{"ReadPipe"}, // 274,
{"WritePipe"}, // 275,
{"ReservedReadPipe"}, // 276,
{"ReservedWritePipe"}, // 277,
{"ReserveReadPipePackets"}, // 278,
{"ReserveWritePipePackets"}, // 279,
{"CommitReadPipe"}, // 280,
{"CommitWritePipe"}, // 281,
{"IsValidReserveId"}, // 282,
{"GetNumPipePackets"}, // 283,
{"GetMaxPipePackets"}, // 284,
{"GroupReserveReadPipePackets"}, // 285,
{"GroupReserveWritePipePackets"}, // 286,
{"GroupCommitReadPipe"}, // 287,
{"GroupCommitWritePipe"}, // 288,
{ nullptr }, // 289
{ nullptr }, // 290
{"EnqueueMarker"}, // 291,
{"EnqueueKernel"}, // 292,
{"GetKernelNDrangeSubGroupCount"}, // 293,
{"GetKernelNDrangeMaxSubGroupSize"}, // 294,
{"GetKernelWorkGroupSize"}, // 295,
{"GetKernelPreferredWorkGroupSizeMultiple"}, // 296,
{"RetainEvent"}, // 297,
{"ReleaseEvent"}, // 298,
{"CreateUserEvent"}, // 299,
{"IsValidEvent"}, // 300,
{"SetUserEventStatus"}, // 301,
{"CaptureEventProfilingInfo"}, // 302,
{"GetDefaultQueue"}, // 303,
{"BuildNDRange"}, // 304,
{"ImageSparseSampleImplicitLod"}, // 305,
{"ImageSparseSampleExplicitLod"}, // 306,
{"ImageSparseSampleDrefImplicitLod"}, // 307,
{"ImageSparseSampleDrefExplicitLod"}, // 308,
{"ImageSparseSampleProjImplicitLod"}, // 309,
{"ImageSparseSampleProjExplicitLod"}, // 310,
{"ImageSparseSampleProjDrefImplicitLod"}, // 311,
{"ImageSparseSampleProjDrefExplicitLod"}, // 312,
{"ImageSparseFetch"}, // 313,
{"ImageSparseGather"}, // 314,
{"ImageSparseDrefGather"}, // 315,
{"ImageSparseTexelsResident"}, // 316,
{"NoLine"}, // 317,
{"AtomicFlagTestAndSet"}, // 318,
{"AtomicFlagClear"}, // 319,
};
static std::string ReadSpirvString(const std::vector<uint32_t> &spirv, int offset, int *outOffset = nullptr) {
bool done = false;
std::string temp;
while (!done) {
uint32_t data = spirv[offset++];
for (int i = 0; i < 4; i++) {
char c = (char)(data & 0xff);
if (!c) {
done = true;
break;
}
temp.push_back(data);
data >>= 8;
}
if (offset == (int)spirv.size())
break;
}
if (outOffset)
*outOffset = offset;
return temp;
}
bool DisassembleSPIRV(std::vector<uint32_t> spirv, std::string *output) {
if (spirv.size() < 10) {
*output = "Too small";
return false;
}
uint32_t magic = spirv[0];
uint32_t version = spirv[1];
uint32_t generator = spirv[2];
int bound = (int)spirv[3]; // Max ID used in file.
// spirv[4] is reserved for schema.
std::vector<SpirvID> ids;
ids.resize(bound);
for (int i = 0; i < bound; i++) {
ids[i].name = StringFromFormat("%%%d", i);
}
if (magic != 0x07230203) {
*output = "Not SPIRV";
return false;
}
int indent = 0;
char *buffer = new char[1024 * 1024];
char *p = buffer;
WRITE(p, "// ======= SPIR-V version %08x =======\n// Max ID: %d\n", version, bound); // GLSL ES
int i = 5;
while (i < (int)spirv.size()) {
uint32_t d = spirv[i];
int wordCount = d >> 16;
int opcode = d & 0xFFFF;
// Force to a valid index in the array.
const OpInfo &op = opInfo[opcode >= (int)ARRAY_SIZE(opInfo) ? 0 : opcode];
int target = (i < (int)spirv.size() - 1) ? spirv[(i + 1)] : 0; // Not always, but used often enough that we get it here.
int source, source2, resType;
std::string name;
switch (opcode) {
case spv::OpTypeVoid:
case spv::OpTypeBool:
case spv::OpTypeInt:
case spv::OpTypeFloat:
case spv::OpTypeMatrix:
case spv::OpTypeImage:
case spv::OpTypeSampler:
case spv::OpTypeSampledImage:
case spv::OpTypeRuntimeArray:
case spv::OpTypeOpaque:
case spv::OpTypePointer:
case spv::OpTypeFunction:
case spv::OpTypeEvent:
case spv::OpTypeDeviceEvent:
case spv::OpTypeReserveId:
case spv::OpTypeQueue:
case spv::OpTypePipe:
case spv::OpTypeForwardPointer:
ids[target].name = op.name + 4; // Remove "Type"
ids[target].opcode = opcode;
break;
case spv::OpTypeVector:
source = spirv[i + 2];
source2 = spirv[i + 3];
ids[target].name = ids[source].name + StringFromFormat("%d", source2);
break;
case spv::OpTypeArray:
source = spirv[i + 2];
source2 = spirv[i + 3];
ids[target].name = ids[source].name + "[" + ids[source2].name + "]";
break;
case spv::OpTypeStruct:
{
ids[target].name = "struct" + ids[target].name;
WRITE(p, "struct {\n");
if (wordCount == 3) {
source = spirv[i + 2];
WRITE(p, " %s\n", ids[source].name.c_str());
} else {
int numMembers = (wordCount - 2) / 2;
for (int m = 0; m < numMembers; m++) {
int id = spirv[i + 2 + m];
int type = spirv[i + 2 + m + numMembers];
WRITE(p, " %s %s;\n", ids[type].name.c_str(), ids[id].name.c_str());
}
}
WRITE(p, "};\n");
}
break;
case spv::OpVariable:
resType = spirv[i + 1];
target = spirv[i + 2];
source = spirv[i + 3];
source2 = spirv[i + 4];
ids[target].name = storageClassNames[source];
break;
case spv::OpDecorate:
source = spirv[i + 2];
ids[target].name += std::string("[") + decorationNames[source] + "]";
break;
case spv::OpName:
ids[target].name = ReadSpirvString(spirv, i + 2);
// WRITE(p, "Name %d: '%s'\n", target, ids[target].name.c_str());
break;
case spv::OpMemberName:
break;
case spv::OpStore:
source = spirv[i + 2];
WRITE(p, "Store(%s, %s)\n", ids[target].name.c_str(), ids[source].name.c_str());
break;
case spv::OpLoad:
resType = spirv[i + 1];
target = spirv[i + 2];
source = spirv[i + 3];
WRITE(p, "%s (%s) := Load(%s)\n", ids[target].name.c_str(), ids[resType].name.c_str(), ids[source].name.c_str());
break;
case spv::OpFAdd:
case spv::OpFMul:
case spv::OpFDiv:
case spv::OpFSub:
resType = spirv[i + 2];
source = spirv[i + 3];
source2 = spirv[i + 4];
WRITE(p, "%s (%s) := %s %s %s\n", ids[target].name.c_str(), ids[resType].name.c_str(), ids[source].name.c_str(), op.extra, ids[source2].name.c_str());
break;
case spv::OpCapability:
case spv::OpMemoryModel:
case spv::OpExtInstImport:
case spv::OpExecutionMode:
case spv::OpGroupAsyncCopy:
case spv::OpSource:
case spv::OpExtension:
// hide these for now
break;
case spv::OpEntryPoint:
source = spirv[i + 1];
source2 = spirv[i + 2];
name = ReadSpirvString(spirv, i + 3);
WRITE(p, "EntryPoint %s: '%s' %s : %s\n", executionModelNames[target], ids[source].name.c_str(), ids[source2].name.c_str(), name.c_str());
break;
case spv::OpFunction:
resType = spirv[i + 1];
target = spirv[i + 2];
source = spirv[i + 3];
ids[target].name = ids[resType].name + "()";
WRITE(p, "Function %s {\n", ids[target].name.c_str());
break;
case spv::OpLabel:
WRITE(p, "label %s:\n", ids[target].name.c_str());
break;
case spv::OpReturnValue:
WRITE(p, "return %s\n", ids[target].name.c_str());
break;
case spv::OpReturn:
WRITE(p, "return\n");
break;
case spv::OpFunctionEnd:
WRITE(p, "}\n");
break;
case spv::OpSourceExtension:
break;
default:
WRITE(p, "%s (%d data words)\n", op.name, wordCount - 1);
break;
}
i += wordCount;
}
*output = buffer;
delete[] buffer;
return true;
}
-10
View File
@@ -1,10 +0,0 @@
#pragma once
#include <cstdint>
#include <string>
#include <vector>
// Mostly just a toy to understand SPIR-V better. Not an accurate SPIR-V disassembler,
// and the result will not reassemble.
bool DisassembleSPIRV(std::vector<uint32_t> spirv, std::string *output);
+193 -94
View File
@@ -60,7 +60,7 @@ 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_NVIDIA: return "NVIDIA";
case VULKAN_VENDOR_AMD: return "AMD";
case VULKAN_VENDOR_ARM: return "ARM";
case VULKAN_VENDOR_QUALCOMM: return "Qualcomm";
@@ -77,6 +77,8 @@ const char *PresentModeString(VkPresentModeKHR presentMode) {
case VK_PRESENT_MODE_MAILBOX_KHR: return "MAILBOX";
case VK_PRESENT_MODE_FIFO_KHR: return "FIFO";
case VK_PRESENT_MODE_FIFO_RELAXED_KHR: return "FIFO_RELAXED";
case VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR: return "SHARED_DEMAND_REFRESH_KHR";
case VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR: return "SHARED_CONTINUOUS_REFRESH_KHR";
default: return "UNKNOWN";
}
}
@@ -120,9 +122,6 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
//#if defined(VK_USE_PLATFORM_XCB_KHR)
// instance_extensions_enabled_.push_back(VK_KHR_XCB_SURFACE_EXTENSION_NAME);
//#endif
//#if defined(VK_USE_PLATFORM_MIR_KHR)
// instance_extensions_enabled_.push_back(VK_KHR_MIR_SURFACE_EXTENSION_NAME);
//#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
if (IsInstanceExtensionAvailable(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME)) {
instance_extensions_enabled_.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
@@ -131,18 +130,32 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
#endif
if (flags_ & VULKAN_FLAG_VALIDATE) {
if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_UTILS_EXTENSION_NAME)) {
// Enable the validation layers
for (size_t i = 0; i < ARRAY_SIZE(validationLayers); i++) {
instance_layer_names_.push_back(validationLayers[i]);
device_layer_names_.push_back(validationLayers[i]);
}
instance_extensions_enabled_.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
extensionsLookup_.EXT_debug_utils = true;
} else if (IsInstanceExtensionAvailable(VK_EXT_DEBUG_REPORT_EXTENSION_NAME)) {
for (size_t i = 0; i < ARRAY_SIZE(validationLayers); i++) {
instance_layer_names_.push_back(validationLayers[i]);
device_layer_names_.push_back(validationLayers[i]);
}
instance_extensions_enabled_.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
extensionsLookup_.EXT_debug_report = true;
} else {
ELOG("Validation layer extension not available - not enabling Vulkan validation.");
flags_ &= ~VULKAN_FLAG_VALIDATE;
}
}
if (IsInstanceExtensionAvailable(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME)) {
instance_extensions_enabled_.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
extensionsLookup_.KHR_get_physical_device_properties2 = true;
}
// Validate that all the instance extensions we ask for are actually available.
for (auto ext : instance_extensions_enabled_) {
if (!IsInstanceExtensionAvailable(ext))
@@ -190,7 +203,7 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
return res;
}
VulkanLoadInstanceFunctions(instance_);
VulkanLoadInstanceFunctions(instance_, extensionsLookup_);
if (!CheckLayers(instance_layer_properties_, instance_layer_names_)) {
WLOG("CheckLayers for instance failed");
// init_error_ = "Failed to validate instance layers";
@@ -222,8 +235,25 @@ VkResult VulkanContext::CreateInstance(const CreateInfo &info) {
return res;
}
for (uint32_t i = 0; i < gpu_count; i++) {
vkGetPhysicalDeviceProperties(physical_devices_[i], &physicalDeviceProperties_[i]);
if (extensionsLookup_.KHR_get_physical_device_properties2) {
for (uint32_t i = 0; i < gpu_count; i++) {
VkPhysicalDeviceProperties2 props2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2};
VkPhysicalDevicePushDescriptorPropertiesKHR pushProps{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES_KHR};
VkPhysicalDeviceExternalMemoryHostPropertiesEXT extHostMemProps{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT};
props2.pNext = &pushProps;
pushProps.pNext = &extHostMemProps;
vkGetPhysicalDeviceProperties2KHR(physical_devices_[i], &props2);
// Don't want bad pointers sitting around.
props2.pNext = nullptr;
pushProps.pNext = nullptr;
physicalDeviceProperties_[i].properties = props2.properties;
physicalDeviceProperties_[i].pushDescriptorProperties = pushProps;
physicalDeviceProperties_[i].externalMemoryHostProperties = extHostMemProps;
}
} else {
for (uint32_t i = 0; i < gpu_count; i++) {
vkGetPhysicalDeviceProperties(physical_devices_[i], &physicalDeviceProperties_[i].properties);
}
}
return VK_SUCCESS;
}
@@ -423,7 +453,7 @@ bool VulkanContext::CheckLayers(const std::vector<LayerProperties> &layer_props,
int VulkanContext::GetPhysicalDeviceByName(std::string name) {
for (size_t i = 0; i < physical_devices_.size(); i++) {
if (physicalDeviceProperties_[i].deviceName == name)
if (physicalDeviceProperties_[i].properties.deviceName == name)
return (int)i;
}
return -1;
@@ -505,41 +535,56 @@ void VulkanContext::ChooseDevice(int physical_device) {
ELOG("Could not find a usable depth stencil format.");
}
// This is as good a place as any to do this
// This is as good a place as any to do this.
vkGetPhysicalDeviceMemoryProperties(physical_devices_[physical_device_], &memory_properties);
ILOG("Memory Types (%d):", memory_properties.memoryTypeCount);
for (int i = 0; i < (int)memory_properties.memoryTypeCount; i++) {
// Don't bother printing dummy memory types.
if (!memory_properties.memoryTypes[i].propertyFlags)
continue;
ILOG(" %d: Heap %d; Flags: %s%s%s%s ", i, memory_properties.memoryTypes[i].heapIndex,
(memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) ? "DEVICE_LOCAL " : "",
(memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) ? "HOST_VISIBLE " : "",
(memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) ? "HOST_CACHED " : "",
(memory_properties.memoryTypes[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) ? "HOST_COHERENT " : "");
}
// Optional features
vkGetPhysicalDeviceFeatures(physical_devices_[physical_device_], &featuresAvailable_);
memset(&featuresEnabled_, 0, sizeof(featuresEnabled_));
if (extensionsLookup_.KHR_get_physical_device_properties2) {
VkPhysicalDeviceFeatures2 features2{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR};
vkGetPhysicalDeviceFeatures2KHR(physical_devices_[physical_device_], &features2);
deviceFeatures_.available = features2.features;
} else {
vkGetPhysicalDeviceFeatures(physical_devices_[physical_device_], &deviceFeatures_.available);
}
deviceFeatures_.enabled = {};
// Enable a few safe ones if they are available.
if (featuresAvailable_.dualSrcBlend && physicalDeviceProperties_[physical_device_].vendorID != VULKAN_VENDOR_QUALCOMM) {
featuresEnabled_.dualSrcBlend = true;
if (deviceFeatures_.available.dualSrcBlend) {
deviceFeatures_.enabled.dualSrcBlend = true;
}
if (featuresAvailable_.largePoints) {
featuresEnabled_.largePoints = true;
if (deviceFeatures_.available.largePoints) {
deviceFeatures_.enabled.largePoints = true;
}
if (featuresAvailable_.wideLines) {
featuresEnabled_.wideLines = true;
if (deviceFeatures_.available.wideLines) {
deviceFeatures_.enabled.wideLines = true;
}
if (featuresAvailable_.geometryShader) {
featuresEnabled_.geometryShader = true;
if (deviceFeatures_.available.logicOp) {
deviceFeatures_.enabled.logicOp = true;
}
if (featuresAvailable_.logicOp) {
featuresEnabled_.logicOp = true;
if (deviceFeatures_.available.depthClamp) {
deviceFeatures_.enabled.depthClamp = true;
}
if (featuresAvailable_.depthClamp) {
featuresEnabled_.depthClamp = true;
if (deviceFeatures_.available.depthBounds) {
deviceFeatures_.enabled.depthBounds = true;
}
if (featuresAvailable_.depthBounds) {
featuresEnabled_.depthBounds = true;
}
if (featuresAvailable_.samplerAnisotropy) {
featuresEnabled_.samplerAnisotropy = true;
if (deviceFeatures_.available.samplerAnisotropy) {
deviceFeatures_.enabled.samplerAnisotropy = true;
}
// For easy wireframe mode, someday.
if (featuresEnabled_.fillModeNonSolid) {
featuresEnabled_.fillModeNonSolid = true;
if (deviceFeatures_.available.fillModeNonSolid) {
deviceFeatures_.enabled.fillModeNonSolid = true;
}
GetDeviceLayerExtensionList(nullptr, device_extension_properties_);
@@ -563,8 +608,8 @@ VkResult VulkanContext::CreateDevice() {
return VK_ERROR_INITIALIZATION_FAILED;
}
VkDeviceQueueCreateInfo queue_info{ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO };
float queue_priorities[1] = { 1.0f };
VkDeviceQueueCreateInfo queue_info{VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO};
float queue_priorities[1] = {1.0f};
queue_info.queueCount = 1;
queue_info.pQueuePriorities = queue_priorities;
bool found = false;
@@ -577,7 +622,25 @@ VkResult VulkanContext::CreateDevice() {
}
assert(found);
deviceExtensionsLookup_.DEDICATED_ALLOCATION = EnableDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
extensionsLookup_.KHR_maintenance1 = EnableDeviceExtension(VK_KHR_MAINTENANCE1_EXTENSION_NAME);
extensionsLookup_.KHR_maintenance2 = EnableDeviceExtension(VK_KHR_MAINTENANCE2_EXTENSION_NAME);
extensionsLookup_.KHR_maintenance3 = EnableDeviceExtension(VK_KHR_MAINTENANCE3_EXTENSION_NAME);
extensionsLookup_.KHR_multiview = EnableDeviceExtension(VK_KHR_MULTIVIEW_EXTENSION_NAME);
if (EnableDeviceExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME)) {
extensionsLookup_.KHR_get_memory_requirements2 = true;
extensionsLookup_.KHR_dedicated_allocation = EnableDeviceExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME);
}
if (EnableDeviceExtension(VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME)) {
if (EnableDeviceExtension(VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME)) {
extensionsLookup_.EXT_external_memory_host = EnableDeviceExtension(VK_EXT_EXTERNAL_MEMORY_HOST_EXTENSION_NAME);
}
}
if (EnableDeviceExtension(VK_KHR_CREATE_RENDERPASS_2_EXTENSION_NAME)) {
extensionsLookup_.KHR_create_renderpass2 = true;
extensionsLookup_.KHR_depth_stencil_resolve = EnableDeviceExtension(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME);
}
extensionsLookup_.EXT_shader_stencil_export = EnableDeviceExtension(VK_EXT_SHADER_STENCIL_EXPORT_EXTENSION_NAME);
VkDeviceCreateInfo device_info{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
device_info.queueCreateInfoCount = 1;
@@ -586,13 +649,14 @@ VkResult VulkanContext::CreateDevice() {
device_info.ppEnabledLayerNames = device_info.enabledLayerCount ? device_layer_names_.data() : nullptr;
device_info.enabledExtensionCount = (uint32_t)device_extensions_enabled_.size();
device_info.ppEnabledExtensionNames = device_info.enabledExtensionCount ? device_extensions_enabled_.data() : nullptr;
device_info.pEnabledFeatures = &featuresEnabled_;
device_info.pEnabledFeatures = &deviceFeatures_.enabled;
VkResult res = vkCreateDevice(physical_devices_[physical_device_], &device_info, nullptr, &device_);
if (res != VK_SUCCESS) {
init_error_ = "Unable to create Vulkan device";
ELOG("Unable to create Vulkan device");
} else {
VulkanLoadDeviceFunctions(device_);
VulkanLoadDeviceFunctions(device_, extensionsLookup_);
}
ILOG("Device created.\n");
VulkanSetAvailable(true);
@@ -608,13 +672,11 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun
}
ILOG("Registering debug report callback");
VkDebugReportCallbackCreateInfoEXT cb = {};
cb.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
cb.pNext = nullptr;
VkDebugReportCallbackCreateInfoEXT cb{VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT};
cb.flags = bits;
cb.pfnCallback = dbgFunc;
cb.pUserData = userdata;
VkResult res = dyn_vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback);
VkResult res = vkCreateDebugReportCallbackEXT(instance_, &cb, nullptr, &msg_callback);
switch (res) {
case VK_SUCCESS:
msg_callbacks.push_back(msg_callback);
@@ -628,49 +690,66 @@ VkResult VulkanContext::InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFun
}
void VulkanContext::DestroyDebugMsgCallback() {
if (!extensionsLookup_.EXT_debug_report)
return;
while (msg_callbacks.size() > 0) {
dyn_vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr);
vkDestroyDebugReportCallbackEXT(instance_, msg_callbacks.back(), nullptr);
msg_callbacks.pop_back();
}
}
void VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2, int width, int height) {
VkResult VulkanContext::InitDebugUtilsCallback(PFN_vkDebugUtilsMessengerCallbackEXT callback, int bits, void *userdata) {
VkDebugUtilsMessengerCreateInfoEXT callback1{VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT};
callback1.messageSeverity = bits;
callback1.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
callback1.pfnUserCallback = callback;
callback1.pUserData = userdata;
VkDebugUtilsMessengerEXT messenger;
VkResult res = vkCreateDebugUtilsMessengerEXT(instance_, &callback1, nullptr, &messenger);
if (res != VK_SUCCESS) {
ELOG("Failed to register debug callback with vkCreateDebugUtilsMessengerEXT");
// Do error handling for VK_ERROR_OUT_OF_MEMORY
} else {
ILOG("Debug callback registered with vkCreateDebugUtilsMessengerEXT.");
utils_callbacks.push_back(messenger);
}
return res;
}
void VulkanContext::DestroyDebugUtilsCallback() {
if (!extensionsLookup_.EXT_debug_utils)
return;
while (utils_callbacks.size() > 0) {
vkDestroyDebugUtilsMessengerEXT(instance_, utils_callbacks.back(), nullptr);
utils_callbacks.pop_back();
}
}
VkResult VulkanContext::InitSurface(WindowSystem winsys, void *data1, void *data2) {
winsys_ = winsys;
winsysData1_ = data1;
winsysData2_ = data2;
ReinitSurface(width, height);
return ReinitSurface();
}
void VulkanContext::ReinitSurface(int width, int height) {
VkResult VulkanContext::ReinitSurface() {
if (surface_ != VK_NULL_HANDLE) {
ILOG("Destroying Vulkan surface (%d, %d)", width_, height_);
ILOG("Destroying Vulkan surface (%d, %d)", swapChainExtent_.width, swapChainExtent_.height);
vkDestroySurfaceKHR(instance_, surface_, nullptr);
surface_ = VK_NULL_HANDLE;
}
ILOG("Creating Vulkan surface (%d, %d)", width, height);
ILOG("Creating Vulkan surface for window");
switch (winsys_) {
#ifdef _WIN32
case WINDOWSYSTEM_WIN32:
{
HINSTANCE connection = (HINSTANCE)winsysData1_;
HWND window = (HWND)winsysData2_;
if (width < 0 || height < 0)
{
RECT rc;
GetClientRect(window, &rc);
width = rc.right - rc.left;
height = rc.bottom - rc.top;
}
VkWin32SurfaceCreateInfoKHR win32{ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR };
win32.flags = 0;
win32.hwnd = window;
win32.hinstance = connection;
VkResult res = vkCreateWin32SurfaceKHR(instance_, &win32, nullptr, &surface_);
assert(res == VK_SUCCESS);
break;
win32.hwnd = (HWND)winsysData2_;
win32.hinstance = (HINSTANCE)winsysData1_;
return vkCreateWin32SurfaceKHR(instance_, &win32, nullptr, &surface_);
}
#endif
#if defined(__ANDROID__)
@@ -680,54 +759,44 @@ void VulkanContext::ReinitSurface(int width, int height) {
VkAndroidSurfaceCreateInfoKHR android{ VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR };
android.flags = 0;
android.window = wnd;
VkResult res = vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_);
assert(res == VK_SUCCESS);
break;
return vkCreateAndroidSurfaceKHR(instance_, &android, nullptr, &surface_);
}
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
case WINDOWSYSTEM_XLIB:
{
VkXlibSurfaceCreateInfoKHR xlib = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR };
VkXlibSurfaceCreateInfoKHR xlib{ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR };
xlib.flags = 0;
xlib.dpy = (Display *)winsysData1_;
xlib.window = (Window)winsysData2_;
VkResult res = vkCreateXlibSurfaceKHR(instance_, &xlib, nullptr, &surface_);
assert(res == VK_SUCCESS);
break;
return vkCreateXlibSurfaceKHR(instance_, &xlib, nullptr, &surface_);
}
#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
case WINDOWSYSTEM_XCB:
{
VkXCBSurfaceCreateInfoKHR xcb = { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR };
VkXCBSurfaceCreateInfoKHR xcb{ VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR };
xcb.flags = 0;
xcb.connection = (Connection *)winsysData1_;
xcb.window = (Window)(uintptr_t)winsysData2_;
VkResult res = vkCreateXcbSurfaceKHR(instance_, &xcb, nullptr, &surface_);
assert(res == VK_SUCCESS);
break;
return vkCreateXcbSurfaceKHR(instance_, &xcb, nullptr, &surface_);
}
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
case WINDOWSYSTEM_WAYLAND:
{
VkWaylandSurfaceCreateInfoKHR wayland = { VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR };
VkWaylandSurfaceCreateInfoKHR wayland{ VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR };
wayland.flags = 0;
wayland.display = (wl_display *)winsysData1_;
wayland.surface = (wl_surface *)winsysData2_;
VkResult res = vkCreateWaylandSurfaceKHR(instance_, &wayland, nullptr, &surface_);
assert(res == VK_SUCCESS);
break;
return vkCreateWaylandSurfaceKHR(instance_, &wayland, nullptr, &surface_);
}
#endif
default:
_assert_msg_(G3D, false, "Vulkan support for chosen window system not implemented");
break;
return VK_ERROR_INITIALIZATION_FAILED;
}
width_ = width;
height_ = height;
}
bool VulkanContext::InitQueue() {
@@ -818,6 +887,14 @@ bool VulkanContext::InitQueue() {
return true;
}
int clamp(int x, int a, int b) {
if (x < a)
return a;
if (x > b)
return b;
return x;
}
bool VulkanContext::InitSwapchain() {
VkResult res = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_devices_[physical_device_], surface_, &surfCapabilities_);
assert(res == VK_SUCCESS);
@@ -829,19 +906,20 @@ bool VulkanContext::InitSwapchain() {
res = vkGetPhysicalDeviceSurfacePresentModesKHR(physical_devices_[physical_device_], surface_, &presentModeCount, presentModes);
assert(res == VK_SUCCESS);
VkExtent2D swapChainExtent;
// width and height are either both -1, or both not -1.
if (surfCapabilities_.currentExtent.width == (uint32_t)-1) {
// If the surface size is undefined, the size is set to
// the size of the images requested.
ILOG("initSwapchain: %dx%d", width_, height_);
swapChainExtent.width = width_;
swapChainExtent.height = height_;
} else {
// If the surface size is defined, the swap chain size must match
swapChainExtent = surfCapabilities_.currentExtent;
ILOG("surfCapabilities_.currentExtent: %dx%d", surfCapabilities_.currentExtent.width, surfCapabilities_.currentExtent.height);
ILOG("surfCapabilities_.minImageExtent: %dx%d", surfCapabilities_.minImageExtent.width, surfCapabilities_.minImageExtent.height);
ILOG("surfCapabilities_.maxImageExtent: %dx%d", surfCapabilities_.maxImageExtent.width, surfCapabilities_.maxImageExtent.height);
swapChainExtent_.width = clamp(surfCapabilities_.currentExtent.width, surfCapabilities_.minImageExtent.width, surfCapabilities_.maxImageExtent.width);
swapChainExtent_.height = clamp(surfCapabilities_.currentExtent.height, surfCapabilities_.minImageExtent.height, surfCapabilities_.maxImageExtent.height);
if (physicalDeviceProperties_[physical_device_].properties.vendorID == VULKAN_VENDOR_IMGTEC) {
// Swap chain width hack to avoid issue #11743 (PowerVR driver bug).
swapChainExtent_.width &= ~31;
}
ILOG("swapChainExtent: %dx%d", swapChainExtent_.width, swapChainExtent_.height);
// TODO: Find a better way to specify the prioritized present mode while being able
// to fall back in a sensible way.
VkPresentModeKHR swapchainPresentMode = VK_PRESENT_MODE_MAX_ENUM_KHR;
@@ -891,13 +969,13 @@ bool VulkanContext::InitSwapchain() {
preTransform = surfCapabilities_.currentTransform;
}
VkSwapchainCreateInfoKHR swap_chain_info = { VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
VkSwapchainCreateInfoKHR swap_chain_info{ VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR };
swap_chain_info.surface = surface_;
swap_chain_info.minImageCount = desiredNumberOfSwapChainImages;
swap_chain_info.imageFormat = swapchainFormat_;
swap_chain_info.imageColorSpace = VK_COLORSPACE_SRGB_NONLINEAR_KHR;
swap_chain_info.imageExtent.width = swapChainExtent.width;
swap_chain_info.imageExtent.height = swapChainExtent.height;
swap_chain_info.imageExtent.width = swapChainExtent_.width;
swap_chain_info.imageExtent.height = swapChainExtent_.height;
swap_chain_info.preTransform = preTransform;
swap_chain_info.imageArrayLayers = 1;
swap_chain_info.presentMode = swapchainPresentMode;
@@ -1241,3 +1319,24 @@ void VulkanDeleteList::PerformDeletes(VkDevice device) {
}
descSetLayouts_.clear();
}
void VulkanContext::GetImageMemoryRequirements(VkImage image, VkMemoryRequirements *mem_reqs, bool *dedicatedAllocation) {
if (DeviceExtensions().KHR_dedicated_allocation) {
VkImageMemoryRequirementsInfo2KHR memReqInfo2{VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2_KHR};
memReqInfo2.image = image;
VkMemoryRequirements2KHR memReq2 = {VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2_KHR};
VkMemoryDedicatedRequirementsKHR memDedicatedReq{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS_KHR};
memReq2.pNext = &memDedicatedReq;
vkGetImageMemoryRequirements2KHR(GetDevice(), &memReqInfo2, &memReq2);
*mem_reqs = memReq2.memoryRequirements;
*dedicatedAllocation =
(memDedicatedReq.requiresDedicatedAllocation != VK_FALSE) ||
(memDedicatedReq.prefersDedicatedAllocation != VK_FALSE);
} else {
vkGetImageMemoryRequirements(GetDevice(), image, mem_reqs);
*dedicatedAllocation = false;
}
}
+36 -21
View File
@@ -101,11 +101,6 @@ private:
std::vector<Callback> callbacks_;
};
// For fast extension-enabled checks.
struct VulkanDeviceExtensions {
bool DEDICATED_ALLOCATION;
};
// Useful for debugging on ARM Mali. This eliminates transaction elimination
// which can cause artifacts if you get barriers wrong (or if there are driver bugs).
// Cost is reduced performance on some GPU architectures.
@@ -142,8 +137,9 @@ public:
VulkanDeleteList &Delete() { return globalDeleteList_; }
// The parameters are whatever the chosen window system wants.
void InitSurface(WindowSystem winsys, void *data1, void *data2, int width = -1, int height = -1);
void ReinitSurface(int width = -1, int height = -1);
// The extents will be automatically determined.
VkResult InitSurface(WindowSystem winsys, void *data1, void *data2);
VkResult ReinitSurface();
bool InitQueue();
bool InitObjects();
@@ -160,15 +156,19 @@ public:
VkFence CreateFence(bool presignalled);
bool CreateShaderModule(const std::vector<uint32_t> &spirv, VkShaderModule *shaderModule);
int GetBackbufferWidth() { return width_; }
int GetBackbufferHeight() { return height_; }
int GetBackbufferWidth() { return (int)swapChainExtent_.width; }
int GetBackbufferHeight() { return (int)swapChainExtent_.height; }
void BeginFrame();
void EndFrame();
bool MemoryTypeFromProperties(uint32_t typeBits, VkFlags requirements_mask, uint32_t *typeIndex);
VkResult InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFunc, int bits, void *userdata = nullptr);
VkResult InitDebugUtilsCallback(PFN_vkDebugUtilsMessengerCallbackEXT callback, int bits, void *userdata);
void DestroyDebugUtilsCallback();
// Legacy reporting
VkResult InitDebugMsgCallback(PFN_vkDebugReportCallbackEXT dbgFunc, int bits, void *userdata);
void DestroyDebugMsgCallback();
VkPhysicalDevice GetPhysicalDevice(int n = 0) const {
@@ -189,7 +189,15 @@ public:
return graphics_queue_family_index_;
}
const VkPhysicalDeviceProperties &GetPhysicalDeviceProperties(int i) const {
struct PhysicalDeviceProps {
VkPhysicalDeviceProperties properties;
VkPhysicalDevicePushDescriptorPropertiesKHR pushDescriptorProperties;
VkPhysicalDeviceExternalMemoryHostPropertiesEXT externalMemoryHostProperties;
};
const PhysicalDeviceProps &GetPhysicalDeviceProperties(int i = -1) const {
if (i < 0)
i = GetCurrentPhysicalDevice();
return physicalDeviceProperties_[i];
}
@@ -205,8 +213,13 @@ public:
const std::vector<const char *> &GetDeviceExtensionsEnabled() const {
return device_extensions_enabled_;
}
const VkPhysicalDeviceFeatures &GetFeaturesAvailable() const { return featuresAvailable_; }
const VkPhysicalDeviceFeatures &GetFeaturesEnabled() const { return featuresEnabled_; }
struct PhysicalDeviceFeatures {
VkPhysicalDeviceFeatures available{};
VkPhysicalDeviceFeatures enabled{};
};
const PhysicalDeviceFeatures &GetDeviceFeatures() const { return deviceFeatures_; }
const VulkanPhysicalDeviceInfo &GetDeviceInfo() const { return deviceInfo_; }
const VkSurfaceCapabilitiesKHR &GetSurfaceCapabilities() const { return surfCapabilities_; }
@@ -247,7 +260,9 @@ public:
MAX_INFLIGHT_FRAMES = 3,
};
const VulkanDeviceExtensions &DeviceExtensions() { return deviceExtensionsLookup_; }
const VulkanDeviceExtensions &DeviceExtensions() { return extensionsLookup_; }
void GetImageMemoryRequirements(VkImage image, VkMemoryRequirements *mem_reqs, bool *dedicatedAllocation);
private:
// A layer can expose extensions, keep track of those extensions here.
@@ -281,23 +296,23 @@ private:
std::vector<const char *> device_extensions_enabled_;
std::vector<VkExtensionProperties> device_extension_properties_;
VulkanDeviceExtensions deviceExtensionsLookup_{};
VulkanDeviceExtensions extensionsLookup_{};
std::vector<VkPhysicalDevice> physical_devices_;
int physical_device_ = -1;
uint32_t graphics_queue_family_index_ = -1;
std::vector<VkPhysicalDeviceProperties> physicalDeviceProperties_{};
std::vector<PhysicalDeviceProps> physicalDeviceProperties_{};
std::vector<VkQueueFamilyProperties> queue_props;
VkPhysicalDeviceMemoryProperties memory_properties{};
// Custom collection of things that are good to know
VulkanPhysicalDeviceInfo deviceInfo_{};
// Swap chain
int width_ = 0;
int height_ = 0;
// Swap chain extent
VkExtent2D swapChainExtent_{};
int flags_ = 0;
int inflightFrames_ = MAX_INFLIGHT_FRAMES;
@@ -314,14 +329,14 @@ private:
VulkanDeleteList globalDeleteList_;
std::vector<VkDebugReportCallbackEXT> msg_callbacks;
std::vector<VkDebugUtilsMessengerEXT> utils_callbacks;
VkSwapchainKHR swapchain_ = VK_NULL_HANDLE;
VkFormat swapchainFormat_;
uint32_t queue_count = 0;
VkPhysicalDeviceFeatures featuresAvailable_{};
VkPhysicalDeviceFeatures featuresEnabled_{};
PhysicalDeviceFeatures deviceFeatures_;
VkSurfaceCapabilitiesKHR surfCapabilities_{};
+57 -3
View File
@@ -56,7 +56,7 @@ const char *ObjTypeToString(VkDebugReportObjectTypeEXT type) {
}
}
VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData) {
VkBool32 VKAPI_CALL VulkanDebugReportCallback(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData) {
const VulkanLogOptions *options = (const VulkanLogOptions *)pUserData;
std::ostringstream message;
@@ -73,8 +73,6 @@ VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObje
}
message << "[" << pLayerPrefix << "] " << ObjTypeToString(objType) << " Code " << msgCode << " : " << pMsg << "\n";
if (msgCode == 2) // Useless perf warning ("Vertex attribute at location X not consumed by vertex shader")
return false;
if (msgCode == 64) // Another useless perf warning that will be seen less and less as we optimize - vkCmdClearAttachments() issued on command buffer object 0x00000195296C6D40 prior to any Draw Cmds. It is recommended you use RenderPass LOAD_OP_CLEAR on Attachments prior to any Draw.
return false;
if (msgCode == 5)
@@ -105,3 +103,59 @@ VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObje
// keep that behavior here.
return false;
}
VkBool32 VKAPI_CALL VulkanDebugUtilsCallback(
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageType,
const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData,
void* pUserData) {
const VulkanLogOptions *options = (const VulkanLogOptions *)pUserData;
std::ostringstream message;
const char *pMessage = pCallbackData->pMessage;
int messageCode = pCallbackData->messageIdNumber;
const char *pLayerPrefix = "";
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
message << "ERROR(";
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
message << "WARNING(";
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT) {
message << "INFO(";
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT) {
message << "VERBOSE(";
}
if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT) {
message << "perf";
} else if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
message << "general";
} else if (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT) {
message << "validation";
}
message << ":" << pCallbackData->messageIdNumber << ") " << pMessage << "\n";
#ifdef _WIN32
std::string msg = message.str();
OutputDebugStringA(msg.c_str());
if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
if (options->breakOnError && IsDebuggerPresent()) {
DebugBreak();
}
if (options->msgBoxOnError) {
MessageBoxA(NULL, pMessage, "Alert", MB_OK);
}
} else if (messageSeverity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
// Don't break on perf warnings for now, even with a debugger. We log them at least.
if (options->breakOnWarning && IsDebuggerPresent() && 0 == (messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT)) {
DebugBreak();
}
}
#endif
// false indicates that layer should not bail-out of an
// API call that had validation failures. This may mean that the
// app dies inside the driver due to invalid parameter(s).
// That's what would happen without validation layers, so we'll
// keep that behavior here.
return false;
}
+2 -1
View File
@@ -25,4 +25,5 @@ struct VulkanLogOptions {
bool msgBoxOnError;
};
VkBool32 VKAPI_CALL Vulkan_Dbg(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData);
VkBool32 VKAPI_CALL VulkanDebugReportCallback(VkDebugReportFlagsEXT msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, int32_t msgCode, const char* pLayerPrefix, const char* pMsg, void *pUserData);
VkBool32 VKAPI_CALL VulkanDebugUtilsCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *pUserData);
+15 -4
View File
@@ -67,15 +67,19 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
VkResult res = vkCreateImage(vulkan_->GetDevice(), &image_create_info, NULL, &image_);
if (res != VK_SUCCESS) {
_assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
ELOG("vkCreateImage failed: %s", VulkanResultToString(res));
return false;
}
VkMemoryRequirements mem_reqs{};
vkGetImageMemoryRequirements(vulkan_->GetDevice(), image_, &mem_reqs);
bool dedicatedAllocation = false;
vulkan_->GetImageMemoryRequirements(image_, &mem_reqs, &dedicatedAllocation);
if (allocator_) {
if (allocator_ && !dedicatedAllocation) {
offset_ = allocator_->Allocate(mem_reqs, &mem_, Tag());
if (offset_ == VulkanDeviceAllocator::ALLOCATE_FAILED) {
ELOG("Image memory allocation failed (mem_reqs.size=%d, typebits=%08x", (int)mem_reqs.size, (int)mem_reqs.memoryTypeBits);
// Destructor will take care of the image.
return false;
}
} else {
@@ -83,16 +87,21 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
mem_alloc.memoryTypeIndex = 0;
mem_alloc.allocationSize = mem_reqs.size;
VkMemoryDedicatedAllocateInfoKHR dedicatedAllocateInfo{VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO_KHR};
if (dedicatedAllocation) {
dedicatedAllocateInfo.image = image_;
mem_alloc.pNext = &dedicatedAllocateInfo;
}
// Find memory type - don't specify any mapping requirements
bool pass = vulkan_->MemoryTypeFromProperties(mem_reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &mem_alloc.memoryTypeIndex);
_assert_(pass);
res = vkAllocateMemory(vulkan_->GetDevice(), &mem_alloc, NULL, &mem_);
if (res != VK_SUCCESS) {
ELOG("vkAllocateMemory failed: %s", VulkanResultToString(res));
_assert_msg_(G3D, res != VK_ERROR_TOO_MANY_OBJECTS, "Too many Vulkan memory objects!");
_assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
vkDestroyImage(vulkan_->GetDevice(), image_, nullptr);
image_ = VK_NULL_HANDLE;
return false;
}
@@ -101,6 +110,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
res = vkBindImageMemory(vulkan_->GetDevice(), image_, mem_, offset_);
if (res != VK_SUCCESS) {
ELOG("vkBindImageMemory failed: %s", VulkanResultToString(res));
// This leaks the image and memory. Should not really happen though...
_assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
return false;
@@ -144,6 +154,7 @@ bool VulkanTexture::CreateDirect(VkCommandBuffer cmd, int w, int h, int numMips,
res = vkCreateImageView(vulkan_->GetDevice(), &view_info, NULL, &view_);
if (res != VK_SUCCESS) {
ELOG("vkCreateImageView failed: %s", VulkanResultToString(res));
// This leaks the image.
_assert_(res == VK_ERROR_OUT_OF_HOST_MEMORY || res == VK_ERROR_OUT_OF_DEVICE_MEMORY || res == VK_ERROR_TOO_MANY_OBJECTS);
return false;
+90 -14
View File
@@ -193,9 +193,22 @@ PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
PFN_vkQueuePresentKHR vkQueuePresentKHR;
// And the DEBUG_REPORT extension. We dynamically load this.
PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT;
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;
PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT;
PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
#ifdef _WIN32
static HINSTANCE vulkanLibrary;
@@ -246,6 +259,7 @@ bool VulkanMayBeAvailable() {
// Do a hyper minimal initialization and teardown to figure out if there's any chance
// that any sort of Vulkan will be usable.
PFN_vkEnumerateInstanceExtensionProperties localEnumerateInstanceExtensionProperties = LOAD_GLOBAL_FUNC_LOCAL(lib, vkEnumerateInstanceExtensionProperties);
PFN_vkCreateInstance localCreateInstance = LOAD_GLOBAL_FUNC_LOCAL(lib, vkCreateInstance);
PFN_vkEnumeratePhysicalDevices localEnumerate = LOAD_GLOBAL_FUNC_LOCAL(lib, vkEnumeratePhysicalDevices);
PFN_vkDestroyInstance localDestroyInstance = LOAD_GLOBAL_FUNC_LOCAL(lib, vkDestroyInstance);
@@ -256,22 +270,60 @@ bool VulkanMayBeAvailable() {
VkApplicationInfo info{ VK_STRUCTURE_TYPE_APPLICATION_INFO };
std::vector<VkPhysicalDevice> devices;
bool anyGood = false;
const char *instanceExtensions[1]{};
const char *instanceExtensions[2]{};
VkInstance instance = VK_NULL_HANDLE;
VkResult res;
uint32_t physicalDeviceCount = 0;
if (!localCreateInstance || !localEnumerate || !localDestroyInstance || !localGetPhysicalDeviceProperties)
goto bail;
uint32_t instanceExtCount = 1;
bool surfaceExtensionFound = false;
bool platformSurfaceExtensionFound = false;
std::vector<VkExtensionProperties> instanceExts;
instanceExtensions[ci.enabledExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;
#ifdef _WIN32
instanceExtensions[0] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
ci.enabledExtensionCount = 1;
const char * const platformSurfaceExtension = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
#elif defined(__ANDROID__)
instanceExtensions[0] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
ci.enabledExtensionCount = 1;
const char *platformSurfaceExtension = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;
#else
const char *platformSurfaceExtension = 0;
#endif
if (!localEnumerateInstanceExtensionProperties || !localCreateInstance || !localEnumerate || !localDestroyInstance || !localGetPhysicalDeviceProperties)
goto bail;
res = localEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, nullptr);
// Maximum paranoia.
if (res != VK_SUCCESS) {
ELOG("Enumerating VK extensions failed.");
goto bail;
}
if (instanceExtCount == 0) {
ELOG("No VK instance extensions - won't be able to present.");
goto bail;
}
instanceExts.resize(instanceExtCount);
res = localEnumerateInstanceExtensionProperties(nullptr, &instanceExtCount, instanceExts.data());
if (res != VK_SUCCESS) {
ELOG("Enumerating VK extensions failed.");
goto bail;
}
if (platformSurfaceExtension) {
for (auto iter : instanceExts) {
if (!strcmp(iter.extensionName, platformSurfaceExtension)) {
instanceExtensions[ci.enabledExtensionCount++] = platformSurfaceExtension;
platformSurfaceExtensionFound = true;
break;
} else if (!strcmp(iter.extensionName, VK_KHR_SURFACE_EXTENSION_NAME)) {
surfaceExtensionFound = true;
}
}
if (!platformSurfaceExtensionFound || !surfaceExtensionFound) {
ELOG("Platform surface extension not found");
goto bail;
}
}
ci.ppEnabledExtensionNames = instanceExtensions;
ci.enabledLayerCount = 0;
info.apiVersion = VK_API_VERSION_1_0;
@@ -372,7 +424,7 @@ bool VulkanLoad() {
return true;
}
void VulkanLoadInstanceFunctions(VkInstance instance) {
void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanDeviceExtensions &enabledExtensions) {
// OK, let's use the above functions to get the rest.
LOAD_INSTANCE_FUNC(instance, vkDestroyInstance);
LOAD_INSTANCE_FUNC(instance, vkEnumeratePhysicalDevices);
@@ -532,8 +584,25 @@ void VulkanLoadInstanceFunctions(VkInstance instance) {
LOAD_INSTANCE_FUNC(instance, vkDestroySurfaceKHR);
dyn_vkCreateDebugReportCallbackEXT = (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT");
dyn_vkDestroyDebugReportCallbackEXT = (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT");
if (enabledExtensions.KHR_get_physical_device_properties2) {
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceProperties2KHR);
LOAD_INSTANCE_FUNC(instance, vkGetPhysicalDeviceFeatures2KHR);
}
if (enabledExtensions.EXT_debug_report) {
LOAD_INSTANCE_FUNC(instance, vkCreateDebugReportCallbackEXT);
LOAD_INSTANCE_FUNC(instance, vkDestroyDebugReportCallbackEXT);
}
if (enabledExtensions.EXT_debug_utils) {
LOAD_INSTANCE_FUNC(instance, vkCreateDebugUtilsMessengerEXT);
LOAD_INSTANCE_FUNC(instance, vkDestroyDebugUtilsMessengerEXT);
LOAD_INSTANCE_FUNC(instance, vkCmdBeginDebugUtilsLabelEXT);
LOAD_INSTANCE_FUNC(instance, vkCmdEndDebugUtilsLabelEXT);
LOAD_INSTANCE_FUNC(instance, vkCmdInsertDebugUtilsLabelEXT);
LOAD_INSTANCE_FUNC(instance, vkSetDebugUtilsObjectNameEXT);
LOAD_INSTANCE_FUNC(instance, vkSetDebugUtilsObjectTagEXT);
}
WLOG("Vulkan instance functions loaded.");
}
@@ -541,7 +610,7 @@ void VulkanLoadInstanceFunctions(VkInstance instance) {
// On some implementations, loading functions (that have Device as their first parameter) via vkGetDeviceProcAddr may
// increase performance - but then these function pointers will only work on that specific device. Thus, this loader is not very
// good for multi-device.
void VulkanLoadDeviceFunctions(VkDevice device) {
void VulkanLoadDeviceFunctions(VkDevice device, const VulkanDeviceExtensions &enabledExtensions) {
WLOG("Vulkan device functions loaded.");
// TODO: Move more functions VulkanLoadInstanceFunctions to here.
LOAD_DEVICE_FUNC(device, vkCreateSwapchainKHR);
@@ -549,6 +618,13 @@ void VulkanLoadDeviceFunctions(VkDevice device) {
LOAD_DEVICE_FUNC(device, vkGetSwapchainImagesKHR);
LOAD_DEVICE_FUNC(device, vkAcquireNextImageKHR);
LOAD_DEVICE_FUNC(device, vkQueuePresentKHR);
if (enabledExtensions.EXT_external_memory_host) {
LOAD_DEVICE_FUNC(device, vkGetMemoryHostPointerPropertiesEXT);
}
if (enabledExtensions.KHR_dedicated_allocation) {
LOAD_DEVICE_FUNC(device, vkGetBufferMemoryRequirements2KHR);
LOAD_DEVICE_FUNC(device, vkGetImageMemoryRequirements2KHR);
}
}
void VulkanFree() {
+37 -4
View File
@@ -197,15 +197,48 @@ extern PFN_vkQueuePresentKHR vkQueuePresentKHR;
// And the DEBUG_REPORT extension. Since we load this dynamically even in static
// linked mode, we have to rename it :(
extern PFN_vkCreateDebugReportCallbackEXT dyn_vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT dyn_vkDestroyDebugReportCallbackEXT;
extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
extern PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
extern PFN_vkSetDebugUtilsObjectTagEXT vkSetDebugUtilsObjectTagEXT;
// Assorted other extensions.
extern PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
extern PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT;
extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
// For fast extension-enabled checks.
struct VulkanDeviceExtensions {
bool EXT_debug_report;
bool EXT_debug_utils;
bool KHR_maintenance1; // required for KHR_create_renderpass2
bool KHR_maintenance2;
bool KHR_maintenance3;
bool KHR_multiview; // required for KHR_create_renderpass2
bool KHR_get_memory_requirements2;
bool KHR_dedicated_allocation;
bool KHR_create_renderpass2;
bool EXT_external_memory_host;
bool KHR_get_physical_device_properties2;
bool KHR_depth_stencil_resolve;
bool EXT_shader_stencil_export;
// bool EXT_depth_range_unrestricted; // Allows depth outside [0.0, 1.0] in 32-bit float depth buffers.
};
// Way to do a quick check before even attempting to load.
bool VulkanMayBeAvailable();
void VulkanSetAvailable(bool available);
bool VulkanLoad();
void VulkanLoadInstanceFunctions(VkInstance instance);
void VulkanLoadDeviceFunctions(VkDevice device);
void VulkanLoadInstanceFunctions(VkInstance instance, const VulkanDeviceExtensions &enabledExtensions);
void VulkanLoadDeviceFunctions(VkDevice device, const VulkanDeviceExtensions &enabledExtensions);
void VulkanFree();
+8 -10
View File
@@ -191,14 +191,8 @@ size_t VulkanDeviceAllocator::Allocate(const VkMemoryRequirements &reqs, VkDevic
assert(!destroyed_);
uint32_t memoryTypeIndex;
bool pass = vulkan_->MemoryTypeFromProperties(reqs.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &memoryTypeIndex);
assert(pass);
if (!pass) {
return ALLOCATE_FAILED;
}
if (memoryTypeIndex_ == UNDEFINED_MEMORY_TYPE) {
memoryTypeIndex_ = memoryTypeIndex;
} else if (memoryTypeIndex_ != memoryTypeIndex) {
assert(memoryTypeIndex_ == memoryTypeIndex);
ELOG("Failed to pick an appropriate memory type (req: %08x)", reqs.memoryTypeBits);
return ALLOCATE_FAILED;
}
@@ -213,6 +207,8 @@ size_t VulkanDeviceAllocator::Allocate(const VkMemoryRequirements &reqs, VkDevic
// This helps us "creep forward", and also spend less time allocating.
const size_t actualSlab = (lastSlab_ + i) % numSlabs;
Slab &slab = slabs_[actualSlab];
if (slab.memoryTypeIndex != memoryTypeIndex)
continue;
size_t start = slab.nextFree;
while (start < slab.usage.size()) {
@@ -227,7 +223,7 @@ size_t VulkanDeviceAllocator::Allocate(const VkMemoryRequirements &reqs, VkDevic
}
// Okay, we couldn't fit it into any existing slabs. We need a new one.
if (!AllocateSlab(size)) {
if (!AllocateSlab(size, memoryTypeIndex)) {
return ALLOCATE_FAILED;
}
@@ -401,16 +397,17 @@ void VulkanDeviceAllocator::ExecuteFree(FreeInfo *userdata) {
delete userdata;
}
bool VulkanDeviceAllocator::AllocateSlab(VkDeviceSize minBytes) {
bool VulkanDeviceAllocator::AllocateSlab(VkDeviceSize minBytes, int memoryTypeIndex) {
assert(!destroyed_);
if (!slabs_.empty() && minSlabSize_ < maxSlabSize_) {
// We're allocating an additional slab, so rachet up its size.
// TODO: Maybe should not do this when we are allocating a new slab due to memoryTypeIndex not matching?
minSlabSize_ <<= 1;
}
VkMemoryAllocateInfo alloc{ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO };
alloc.allocationSize = minSlabSize_;
alloc.memoryTypeIndex = memoryTypeIndex_;
alloc.memoryTypeIndex = memoryTypeIndex;
while (alloc.allocationSize < minBytes) {
alloc.allocationSize <<= 1;
@@ -427,6 +424,7 @@ bool VulkanDeviceAllocator::AllocateSlab(VkDeviceSize minBytes) {
slabs_.resize(slabs_.size() + 1);
Slab &slab = slabs_[slabs_.size() - 1];
slab.memoryTypeIndex = memoryTypeIndex;
slab.deviceMemory = deviceMemory;
slab.usage.resize((size_t)(alloc.allocationSize >> SLAB_GRAIN_SHIFT));
+2 -2
View File
@@ -174,6 +174,7 @@ private:
struct Slab {
VkDeviceMemory deviceMemory;
uint32_t memoryTypeIndex = UNDEFINED_MEMORY_TYPE;
std::vector<uint8_t> usage;
std::unordered_map<size_t, size_t> allocSizes;
std::unordered_map<size_t, UsageInfo> tags;
@@ -200,7 +201,7 @@ private:
freeInfo->allocator->ExecuteFree(freeInfo); // this deletes freeInfo
}
bool AllocateSlab(VkDeviceSize minBytes);
bool AllocateSlab(VkDeviceSize minBytes, int memoryTypeIndex);
bool AllocateFromSlab(Slab &slab, size_t &start, size_t blocks, const std::string &tag);
void Decimate();
void DoTouch(VkDeviceMemory deviceMemory, size_t offset);
@@ -212,6 +213,5 @@ private:
size_t lastSlab_ = 0;
size_t minSlabSize_;
const size_t maxSlabSize_;
uint32_t memoryTypeIndex_ = UNDEFINED_MEMORY_TYPE;
bool destroyed_ = false;
};
+4
View File
@@ -69,6 +69,10 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
CheckSetting(iniFile, gameID, "MGS2AcidHack", &flags_.MGS2AcidHack);
CheckSetting(iniFile, gameID, "SonicRivalsHack", &flags_.SonicRivalsHack);
CheckSetting(iniFile, gameID, "AdhocHackDisableNBSwitch", &flags_.AdhocHackDisableNBSwitch);
CheckSetting(iniFile, gameID, "BlockTransferAllowCreateFB", &flags_.BlockTransferAllowCreateFB);
CheckSetting(iniFile, gameID, "YugiohSaveFix", &flags_.YugiohSaveFix);
CheckSetting(iniFile, gameID, "ForceUMDDelay", &flags_.ForceUMDDelay);
CheckSetting(iniFile, gameID, "ForceMax60FPS", &flags_.ForceMax60FPS);
}
void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
+4
View File
@@ -69,6 +69,10 @@ struct CompatFlags {
bool MGS2AcidHack;
bool SonicRivalsHack;
bool AdhocHackDisableNBSwitch;
bool BlockTransferAllowCreateFB;
bool YugiohSaveFix;
bool ForceUMDDelay;
bool ForceMax60FPS;
};
class IniFile;
+3 -10
View File
@@ -474,6 +474,7 @@ static ConfigSetting cpuSettings[] = {
ConfigSetting("HideSlowWarnings", &g_Config.bHideSlowWarnings, true, true, false),
ConfigSetting("HideStateWarnings", &g_Config.bHideStateWarnings, false, true, false),
ConfigSetting("PreloadFunctions", &g_Config.bPreloadFunctions, false, true, true),
ConfigSetting("JitDisableFlags", &g_Config.uJitDisableFlags, (uint32_t)0, true, true),
ReportedConfigSetting("CPUSpeed", &g_Config.iLockedCPUSpeed, 0, true, true),
ConfigSetting(false),
@@ -543,12 +544,6 @@ static int DefaultAndroidHwScale() {
}
static int DefaultGPUBackend() {
#if PPSSPP_PLATFORM(WINDOWS) || PPSSPP_PLATFORM(ANDROID)
// Where supported, let's use Vulkan.
if (VulkanMayBeAvailable()) {
return (int)GPUBackend::VULKAN;
}
#endif
#if PPSSPP_PLATFORM(WINDOWS)
// If no Vulkan, use Direct3D 11 on Windows 8+ (most importantly 10.)
if (DoesVersionMatchWindows(6, 2, 0, 0, true)) {
@@ -617,6 +612,7 @@ static ConfigSetting graphicsSettings[] = {
#ifdef _WIN32
ConfigSetting("D3D11Device", &g_Config.sD3D11Device, "", true, false),
#endif
ConfigSetting("VendorBugChecksEnabled", &g_Config.bVendorBugChecksEnabled, true, false, false),
ReportedConfigSetting("RenderingMode", &g_Config.iRenderingMode, &DefaultRenderingMode, true, true),
ConfigSetting("SoftwareRenderer", &g_Config.bSoftwareRendering, false, true, true),
ReportedConfigSetting("HardwareTransform", &g_Config.bHardwareTransform, true, true, true),
@@ -628,6 +624,7 @@ static ConfigSetting graphicsSettings[] = {
ReportedConfigSetting("AndroidHwScale", &g_Config.iAndroidHwScale, &DefaultAndroidHwScale),
ReportedConfigSetting("HighQualityDepth", &g_Config.bHighQualityDepth, true, true, true),
ReportedConfigSetting("FrameSkip", &g_Config.iFrameSkip, 0, true, true),
ReportedConfigSetting("FrameSkipType", &g_Config.iFrameSkipType, 0, true, true),
ReportedConfigSetting("AutoFrameSkip", &g_Config.bAutoFrameSkip, false, true, true),
ConfigSetting("FrameRate", &g_Config.iFpsLimit1, 0, true, true),
ConfigSetting("FrameRate2", &g_Config.iFpsLimit2, -1, true, true),
@@ -635,7 +632,6 @@ static ConfigSetting graphicsSettings[] = {
#if defined(USING_WIN_UI)
ConfigSetting("RestartRequired", &g_Config.bRestartRequired, false, false),
#endif
ReportedConfigSetting("ForceMaxEmulatedFPS", &g_Config.iForceMaxEmulatedFPS, 60, true, true),
ConfigSetting("RefreshAt60Hz", &g_Config.bRefreshAt60Hz, false, true, true),
// Most low-performance (and many high performance) mobile GPUs do not support aniso anyway so defaulting to 4 is fine.
@@ -659,7 +655,6 @@ static ConfigSetting graphicsSettings[] = {
ConfigSetting("SustainedPerformanceMode", &g_Config.bSustainedPerformanceMode, false, true, true),
ConfigSetting("MipMap", &g_Config.bMipMap, true, true, true),
ReportedConfigSetting("TrueColor", &g_Config.bTrueColor, true, true, true),
ReportedConfigSetting("ReplaceTextures", &g_Config.bReplaceTextures, true, true, true),
ReportedConfigSetting("SaveNewTextures", &g_Config.bSaveNewTextures, false, true, true),
ReportedConfigSetting("IgnoreTextureFilenames", &g_Config.bIgnoreTextureFilenames, true, true, false),
@@ -669,11 +664,9 @@ static ConfigSetting graphicsSettings[] = {
ReportedConfigSetting("TexDeposterize", &g_Config.bTexDeposterize, false, true, true),
ReportedConfigSetting("TexRealtime", &g_Config.bRealtimeTexScaling, false, true, true),
ConfigSetting("VSyncInterval", &g_Config.bVSync, true, true, true),
ReportedConfigSetting("DisableStencilTest", &g_Config.bDisableStencilTest, false, true, true),
ReportedConfigSetting("BloomHack", &g_Config.iBloomHack, 2, true, true),
// Not really a graphics setting...
ReportedConfigSetting("TimerHack", &g_Config.bTimerHack, &DefaultTimerHack, true, true),
ReportedConfigSetting("SplineBezierQuality", &g_Config.iSplineBezierQuality, 2, true, true),
ReportedConfigSetting("HardwareTessellation", &g_Config.bHardwareTessellation, false, true, true),
ReportedConfigSetting("PostShader", &g_Config.sPostShaderName, "Off", true, true),
+3 -2
View File
@@ -98,6 +98,7 @@ public:
bool bHideSlowWarnings;
bool bHideStateWarnings;
bool bPreloadFunctions;
uint32_t uJitDisableFlags;
bool bVulkanMultithreading;
bool bSeparateSASThread;
@@ -139,6 +140,7 @@ public:
bool bHardwareTransform; // only used in the GLES backend
bool bSoftwareSkinning; // may speed up some games
bool bShaderDepal;
bool bVendorBugChecksEnabled;
int iRenderingMode; // 0 = non-buffered rendering 1 = buffered rendering
int iTexFiltering; // 1 = off , 2 = nearest , 3 = linear , 4 = linear(CG)
@@ -151,6 +153,7 @@ public:
bool bSustainedPerformanceMode; // Android: Slows clocks down to avoid overheating/speed fluctuations.
bool bVSync;
int iFrameSkip;
int iFrameSkipType;
bool bAutoFrameSkip;
bool bFrameSkipUnthrottle;
@@ -194,9 +197,7 @@ public:
bool bEnableCheats;
bool bReloadCheats;
int iCwCheatRefreshRate;
bool bDisableStencilTest;
int iBloomHack; //0 = off, 1 = safe, 2 = balanced, 3 = aggressive
bool bTimerHack;
bool bBlockTransferGPU;
bool bDisableSlowFramebufEffects;
bool bFragmentTestCache;
+2
View File
@@ -79,6 +79,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ForcedIncludeFiles>Common/DbgNew.h</ForcedIncludeFiles>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
@@ -101,6 +102,7 @@
<RuntimeTypeInfo>false</RuntimeTypeInfo>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ForcedIncludeFiles>Common/DbgNew.h</ForcedIncludeFiles>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
-7
View File
@@ -120,15 +120,8 @@ u64 GetGlobalTimeUsScaled()
{
s64 ticksSinceLast = GetTicks() - lastGlobalTimeTicks;
int freq = GetClockFrequencyMHz();
if (g_Config.bTimerHack) {
float vps;
__DisplayGetVPS(&vps);
if (vps > 4.0f)
freq *= (vps / (g_Config.bRefreshAt60Hz ? 60.0f : 59.94f));
}
s64 usSinceLast = ticksSinceLast / freq;
return lastGlobalTimeUs + usSinceLast;
}
u64 GetGlobalTimeUs()
+7
View File
@@ -24,6 +24,13 @@
#include "net/websocket_server.h"
#include "Common/Log.h"
#include "ppsspp_config.h"
#if PPSSPP_PLATFORM(UWP)
// Enum name overlapped with UWP macro, quick hack to disable it
#undef OPTIONAL
#endif
using namespace json;
static inline void DebuggerJsonAddTicket(JsonWriter &writer, const JsonGet &data) {
+5 -19
View File
@@ -25,12 +25,12 @@
// Takes ownership of backend.
CachingFileLoader::CachingFileLoader(FileLoader *backend)
: backend_(backend) {
: ProxiedFileLoader(backend) {
}
void CachingFileLoader::Prepare() {
std::call_once(preparedFlag_, [this](){
filesize_ = backend_->FileSize();
filesize_ = ProxiedFileLoader::FileSize();
if (filesize_ > 0) {
InitCache();
}
@@ -41,27 +41,25 @@ CachingFileLoader::~CachingFileLoader() {
if (filesize_ > 0) {
ShutdownCache();
}
// Takes ownership.
delete backend_;
}
bool CachingFileLoader::Exists() {
if (exists_ == -1) {
exists_ = backend_->Exists() ? 1 : 0;
exists_ = ProxiedFileLoader::Exists() ? 1 : 0;
}
return exists_ == 1;
}
bool CachingFileLoader::ExistsFast() {
if (exists_ == -1) {
return backend_->ExistsFast();
return ProxiedFileLoader::ExistsFast();
}
return exists_ == 1;
}
bool CachingFileLoader::IsDirectory() {
if (isDirectory_ == -1) {
isDirectory_ = backend_->IsDirectory() ? 1 : 0;
isDirectory_ = ProxiedFileLoader::IsDirectory() ? 1 : 0;
}
return isDirectory_ == 1;
}
@@ -71,10 +69,6 @@ s64 CachingFileLoader::FileSize() {
return filesize_;
}
std::string CachingFileLoader::Path() const {
return backend_->Path();
}
size_t CachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
Prepare();
if (absolutePos >= filesize_) {
@@ -288,11 +282,3 @@ void CachingFileLoader::StartReadAhead(s64 pos) {
});
th.detach();
}
bool CachingFileLoader::IsRemote() {
return backend_->IsRemote();
}
void CachingFileLoader::Cancel() {
backend_->Cancel();
}
+1 -6
View File
@@ -23,25 +23,21 @@
#include "Common/CommonTypes.h"
#include "Core/Loaders.h"
class CachingFileLoader : public FileLoader {
class CachingFileLoader : public ProxiedFileLoader {
public:
CachingFileLoader(FileLoader *backend);
~CachingFileLoader() override;
bool IsRemote() override;
bool Exists() override;
bool ExistsFast() override;
bool IsDirectory() override;
s64 FileSize() override;
std::string Path() const override;
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
}
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
void Cancel() override;
private:
void Prepare();
void InitCache();
@@ -61,7 +57,6 @@ private:
};
s64 filesize_ = 0;
FileLoader *backend_;
int exists_ = -1;
int isDirectory_ = -1;
u64 generation_;
+5 -23
View File
@@ -41,12 +41,12 @@ std::mutex DiskCachingFileLoader::cachesMutex_;
// Takes ownership of backend.
DiskCachingFileLoader::DiskCachingFileLoader(FileLoader *backend)
: backend_(backend) {
: ProxiedFileLoader(backend) {
}
void DiskCachingFileLoader::Prepare() {
std::call_once(preparedFlag_, [this]() {
filesize_ = backend_->FileSize();
filesize_ = ProxiedFileLoader::FileSize();
if (filesize_ > 0) {
InitCache();
}
@@ -57,13 +57,11 @@ DiskCachingFileLoader::~DiskCachingFileLoader() {
if (filesize_ > 0) {
ShutdownCache();
}
// Takes ownership.
delete backend_;
}
bool DiskCachingFileLoader::Exists() {
Prepare();
return backend_->Exists();
return ProxiedFileLoader::Exists();
}
bool DiskCachingFileLoader::ExistsFast() {
@@ -72,19 +70,11 @@ bool DiskCachingFileLoader::ExistsFast() {
return true;
}
bool DiskCachingFileLoader::IsDirectory() {
return backend_->IsDirectory();
}
s64 DiskCachingFileLoader::FileSize() {
Prepare();
return filesize_;
}
std::string DiskCachingFileLoader::Path() const {
return backend_->Path();
}
size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
Prepare();
size_t readSize;
@@ -115,14 +105,6 @@ size_t DiskCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data,
return readSize;
}
bool DiskCachingFileLoader::IsRemote() {
return backend_->IsRemote();
}
void DiskCachingFileLoader::Cancel() {
backend_->Cancel();
}
std::vector<std::string> DiskCachingFileLoader::GetCachedPathsInUse() {
std::lock_guard<std::mutex> guard(cachesMutex_);
@@ -139,7 +121,7 @@ std::vector<std::string> DiskCachingFileLoader::GetCachedPathsInUse() {
void DiskCachingFileLoader::InitCache() {
std::lock_guard<std::mutex> guard(cachesMutex_);
std::string path = backend_->Path();
std::string path = ProxiedFileLoader::Path();
auto &entry = caches_[path];
if (!entry) {
entry = new DiskCachingFileLoaderCache(path, filesize_);
@@ -155,7 +137,7 @@ void DiskCachingFileLoader::ShutdownCache() {
if (cache_->Release()) {
// If it ran out of counts, delete it.
delete cache_;
caches_.erase(backend_->Path());
caches_.erase(ProxiedFileLoader::Path());
}
cache_ = nullptr;
}
+1 -7
View File
@@ -27,25 +27,20 @@
class DiskCachingFileLoaderCache;
class DiskCachingFileLoader : public FileLoader {
class DiskCachingFileLoader : public ProxiedFileLoader {
public:
DiskCachingFileLoader(FileLoader *backend);
~DiskCachingFileLoader() override;
bool IsRemote() override;
bool Exists() override;
bool ExistsFast() override;
bool IsDirectory() override;
s64 FileSize() override;
std::string Path() const override;
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
}
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
void Cancel() override;
static std::vector<std::string> GetCachedPathsInUse();
private:
@@ -55,7 +50,6 @@ private:
std::once_flag preparedFlag_;
s64 filesize_ = 0;
FileLoader *backend_;
DiskCachingFileLoaderCache *cache_ = nullptr;
// We don't support concurrent disk cache access (we use memory cached indexes.)
+11 -1
View File
@@ -28,17 +28,23 @@ HTTPFileLoader::HTTPFileLoader(const std::string &filename)
void HTTPFileLoader::Prepare() {
std::call_once(preparedFlag_, [this](){
if (!client_.Resolve(url_.Host().c_str(), url_.Port())) {
// TODO: Should probably set some flag?
ERROR_LOG(LOADER, "HTTP request failed, unable to resolve: %s port %d", url_.Host().c_str(), url_.Port());
latestError_ = "Could not connect (name not resolved)";
return;
}
client_.SetDataTimeout(20.0);
Connect();
if (!connected_) {
ERROR_LOG(LOADER, "HTTP request failed, failed to connect: %s port %d", url_.Host().c_str(), url_.Port());
latestError_ = "Could not connect (refused to connect)";
return;
}
int err = client_.SendRequest("HEAD", url_.Resource().c_str());
if (err < 0) {
ERROR_LOG(LOADER, "HTTP request failed, failed to send request: %s port %d", url_.Host().c_str(), url_.Port());
latestError_ = "Could not connect (could not request data)";
Disconnect();
return;
}
@@ -49,6 +55,7 @@ void HTTPFileLoader::Prepare() {
if (code != 200) {
// Leave size at 0, invalid.
ERROR_LOG(LOADER, "HTTP request failed, got %03d for %s", code, filename_.c_str());
latestError_ = "Could not connect (invalid response)";
Disconnect();
return;
}
@@ -138,6 +145,7 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
int err = client_.SendRequest("GET", url_.Resource().c_str(), requestHeaders, nullptr);
if (err < 0) {
latestError_ = "Invalid response reading data";
Disconnect();
return 0;
}
@@ -147,6 +155,7 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
int code = client_.ReadResponseHeaders(&readbuf, responseHeaders);
if (code != 206) {
ERROR_LOG(LOADER, "HTTP server did not respond with range, received code=%03d", code);
latestError_ = "Invalid response reading data";
Disconnect();
return 0;
}
@@ -185,6 +194,7 @@ size_t HTTPFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags f
if (!supportedResponse) {
ERROR_LOG(LOADER, "HTTP server did not respond with the range we wanted.");
latestError_ = "Invalid response reading data";
return 0;
}
+5
View File
@@ -48,6 +48,10 @@ public:
cancelConnect_ = true;
}
std::string LatestError() const override {
return latestError_;
}
private:
void Prepare();
@@ -67,6 +71,7 @@ private:
std::string filename_;
bool connected_ = false;
bool cancelConnect_ = false;
const char *latestError_ = "";
std::once_flag preparedFlag_;
std::mutex readAtMutex_;
+5 -15
View File
@@ -28,7 +28,7 @@
// Takes ownership of backend.
RamCachingFileLoader::RamCachingFileLoader(FileLoader *backend)
: backend_(backend) {
: ProxiedFileLoader(backend) {
filesize_ = backend->FileSize();
if (filesize_ > 0) {
InitCache();
@@ -39,27 +39,25 @@ RamCachingFileLoader::~RamCachingFileLoader() {
if (filesize_ > 0) {
ShutdownCache();
}
// Takes ownership.
delete backend_;
}
bool RamCachingFileLoader::Exists() {
if (exists_ == -1) {
exists_ = backend_->Exists() ? 1 : 0;
exists_ = ProxiedFileLoader::Exists() ? 1 : 0;
}
return exists_ == 1;
}
bool RamCachingFileLoader::ExistsFast() {
if (exists_ == -1) {
return backend_->ExistsFast();
return ProxiedFileLoader::ExistsFast();
}
return exists_ == 1;
}
bool RamCachingFileLoader::IsDirectory() {
if (isDirectory_ == -1) {
isDirectory_ = backend_->IsDirectory() ? 1 : 0;
isDirectory_ = ProxiedFileLoader::IsDirectory() ? 1 : 0;
}
return isDirectory_ == 1;
}
@@ -68,10 +66,6 @@ s64 RamCachingFileLoader::FileSize() {
return filesize_;
}
std::string RamCachingFileLoader::Path() const {
return backend_->Path();
}
size_t RamCachingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
size_t readSize = 0;
if (cache_ == nullptr || (flags & Flags::HINT_UNCACHED) != 0) {
@@ -129,7 +123,7 @@ void RamCachingFileLoader::Cancel() {
aheadCancel_ = true;
}
backend_->Cancel();
ProxiedFileLoader::Cancel();
}
size_t RamCachingFileLoader::ReadFromCache(s64 pos, size_t bytes, void *data) {
@@ -270,7 +264,3 @@ u32 RamCachingFileLoader::NextAheadBlock() {
return 0xFFFFFFFF;
}
bool RamCachingFileLoader::IsRemote() {
return backend_->IsRemote();
}
+1 -4
View File
@@ -23,17 +23,15 @@
#include "Common/CommonTypes.h"
#include "Core/Loaders.h"
class RamCachingFileLoader : public FileLoader {
class RamCachingFileLoader : public ProxiedFileLoader {
public:
RamCachingFileLoader(FileLoader *backend);
~RamCachingFileLoader() override;
bool IsRemote() override;
bool Exists() override;
bool ExistsFast() override;
bool IsDirectory() override;
s64 FileSize() override;
std::string Path() const override;
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
@@ -59,7 +57,6 @@ private:
};
s64 filesize_ = 0;
FileLoader *backend_;
u8 *cache_ = nullptr;
int exists_ = -1;
int isDirectory_ = -1;
+8 -25
View File
@@ -19,47 +19,38 @@
// Takes ownership of backend.
RetryingFileLoader::RetryingFileLoader(FileLoader *backend)
: backend_(backend) {
}
RetryingFileLoader::~RetryingFileLoader() {
// Takes ownership.
delete backend_;
: ProxiedFileLoader(backend) {
}
bool RetryingFileLoader::Exists() {
if (!backend_->Exists()) {
if (!ProxiedFileLoader::Exists()) {
// Retry once, immediately.
return backend_->Exists();
return ProxiedFileLoader::Exists();
}
return true;
}
bool RetryingFileLoader::ExistsFast() {
if (!backend_->ExistsFast()) {
if (!ProxiedFileLoader::ExistsFast()) {
// Retry once, immediately.
return backend_->ExistsFast();
return ProxiedFileLoader::ExistsFast();
}
return true;
}
bool RetryingFileLoader::IsDirectory() {
// Can't tell if it's an error either way.
return backend_->IsDirectory();
return ProxiedFileLoader::IsDirectory();
}
s64 RetryingFileLoader::FileSize() {
s64 filesize = backend_->FileSize();
s64 filesize = ProxiedFileLoader::FileSize();
if (filesize == 0) {
return backend_->FileSize();
return ProxiedFileLoader::FileSize();
}
return filesize;
}
std::string RetryingFileLoader::Path() const {
return backend_->Path();
}
size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags) {
size_t readSize = backend_->ReadAt(absolutePos, bytes, data, flags);
@@ -72,11 +63,3 @@ size_t RetryingFileLoader::ReadAt(s64 absolutePos, size_t bytes, void *data, Fla
return readSize;
}
bool RetryingFileLoader::IsRemote() {
return backend_->IsRemote();
}
void RetryingFileLoader::Cancel() {
backend_->Cancel();
}
+1 -8
View File
@@ -20,29 +20,22 @@
#include "Common/CommonTypes.h"
#include "Core/Loaders.h"
class RetryingFileLoader : public FileLoader {
class RetryingFileLoader : public ProxiedFileLoader {
public:
RetryingFileLoader(FileLoader *backend);
~RetryingFileLoader() override;
bool IsRemote() override;
bool Exists() override;
bool ExistsFast() override;
bool IsDirectory() override;
s64 FileSize() override;
std::string Path() const override;
size_t ReadAt(s64 absolutePos, size_t bytes, size_t count, void *data, Flags flags = Flags::NONE) override {
return ReadAt(absolutePos, bytes * count, data, flags) / bytes;
}
size_t ReadAt(s64 absolutePos, size_t bytes, void *data, Flags flags = Flags::NONE) override;
void Cancel() override;
private:
enum {
MAX_RETRIES = 3,
};
FileLoader *backend_;
};
+5 -6
View File
@@ -66,9 +66,6 @@ static bool FixFilenameCase(const std::string &path, std::string &filename)
}
//TODO: lookup filename in cache for "path"
struct dirent_large { struct dirent entry; char padding[FILENAME_MAX+1]; } diren;
struct dirent_large;
struct dirent *result = NULL;
DIR *dirp = opendir(path.c_str());
@@ -77,7 +74,7 @@ static bool FixFilenameCase(const std::string &path, std::string &filename)
bool retValue = false;
while (!readdir_r(dirp, (dirent*) &diren, &result) && result)
while ((result = readdir(dirp)))
{
if (strlen(result->d_name) != filenameSize)
continue;
@@ -281,8 +278,10 @@ bool DirectoryFileHandle::Open(std::string &basePath, std::string &fileName, Fil
#if HOST_IS_CASE_SENSITIVE
if (!success && !(access & FILEACCESS_CREATE)) {
if (!FixPathCase(basePath,fileName, FPC_PATH_MUST_EXIST) )
return 0; // or go on and attempt (for a better error code than just 0?)
if (!FixPathCase(basePath, fileName, FPC_PATH_MUST_EXIST)) {
error = SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND;
return false;
}
fullName = GetLocalPath(basePath,fileName);
const char *fullNameC = fullName.c_str();
+1 -1
View File
@@ -661,7 +661,7 @@ static int Hook_hexyzforce_monoclome_thread() {
static int Hook_starocean_write_stencil() {
const u32 fb_address = currentMIPS->r[MIPS_REG_T7];
if (Memory::IsVRAMAddress(fb_address) && !g_Config.bDisableStencilTest) {
if (Memory::IsVRAMAddress(fb_address)) {
gpu->PerformStencilUpload(fb_address, 0x00088000);
}
return 0;
+20 -6
View File
@@ -503,6 +503,18 @@ static void DoFrameDropLogging(float scaledTimestep) {
}
}
static int CalculateFrameSkip() {
int frameSkipNum;
if (g_Config.iFrameSkipType == 1) {
// Calculate the frames to skip dynamically using the set percentage of the current fps
frameSkipNum = ceil( flips * (static_cast<double>(g_Config.iFrameSkip) / 100.00) );
} else {
// Use the set number of frames to skip
frameSkipNum = g_Config.iFrameSkip;
}
return frameSkipNum;
}
// Let's collect all the throttling and frameskipping logic here.
static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
PROFILE_THIS_SCOPE("timing");
@@ -553,15 +565,16 @@ static void DoFrameTiming(bool &throttle, bool &skipFrame, float timestep) {
// Auto-frameskip automatically if speed limit is set differently than the default.
bool useAutoFrameskip = g_Config.bAutoFrameSkip && g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
bool forceFrameskip = (fpsLimiter == FPSLimit::CUSTOM1 && g_Config.iFpsLimit1 > 60) || (fpsLimiter == FPSLimit::CUSTOM2 && g_Config.iFpsLimit2 > 60);
int frameSkipNum = CalculateFrameSkip();
if (g_Config.bAutoFrameSkip || forceFrameskip) {
// autoframeskip
// Argh, we are falling behind! Let's skip a frame and see if we catch up.
if (curFrameTime > nextFrameTime && doFrameSkip) {
skipFrame = true;
}
} else if (g_Config.iFrameSkip >= 1) {
} else if (frameSkipNum >= 1) {
// fixed frameskip
if (numSkippedFrames >= g_Config.iFrameSkip)
if (numSkippedFrames >= frameSkipNum)
skipFrame = false;
else
skipFrame = true;
@@ -734,9 +747,10 @@ void __DisplayFlip(int cyclesLate) {
DoFrameTiming(throttle, skipFrame, (float)numVBlanksSinceFlip * timePerVblank);
int maxFrameskip = 8;
int frameSkipNum = CalculateFrameSkip();
if (throttle) {
// 4 here means 1 drawn, 4 skipped - so 12 fps minimum.
maxFrameskip = g_Config.iFrameSkip;
maxFrameskip = frameSkipNum;
}
if (numSkippedFrames >= maxFrameskip || GPURecord::IsActivePending()) {
skipFrame = false;
@@ -914,7 +928,7 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync)
s64 delayCycles = 0;
// Don't count transitions between display off and display on.
if (topaddr != 0 && topaddr != framebuf.topaddr && framebuf.topaddr != 0 && g_Config.iForceMaxEmulatedFPS > 0) {
if (topaddr != 0 && topaddr != framebuf.topaddr && framebuf.topaddr != 0 && PSP_CoreParameter().compat.flags().ForceMax60FPS) {
// sceDisplaySetFramebuf() isn't supposed to delay threads at all. This is a hack.
// So let's only delay when it's more than 1ms.
const s64 FLIP_DELAY_CYCLES_MIN = usToCycles(1000);
@@ -928,7 +942,7 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync)
u64 now = CoreTiming::GetTicks();
s64 cyclesAhead = nextFlipCycles - now;
if (cyclesAhead > FLIP_DELAY_CYCLES_MIN) {
if (lastFlipsTooFrequent >= FLIP_DELAY_MIN_FLIPS && gpuStats.numClears > 0) {
if (lastFlipsTooFrequent >= FLIP_DELAY_MIN_FLIPS) {
delayCycles = cyclesAhead;
} else {
++lastFlipsTooFrequent;
@@ -938,7 +952,7 @@ u32 sceDisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync)
}
// 1001 to account for NTSC timing (59.94 fps.)
u64 expected = msToCycles(g_Config.bRefreshAt60Hz ? 1000 : 1001) / g_Config.iForceMaxEmulatedFPS - LEEWAY_CYCLES_PER_FLIP;
u64 expected = msToCycles(g_Config.bRefreshAt60Hz ? 1000 : 1001) / 60 - LEEWAY_CYCLES_PER_FLIP;
lastFlipCycles = now;
nextFlipCycles = std::max(lastFlipCycles, nextFlipCycles) + expected;
}
+21 -10
View File
@@ -253,6 +253,14 @@ public:
u64 __IoCompleteAsyncIO(FileNode *f);
static int GetIOTimingMethod() {
if (PSP_CoreParameter().compat.flags().ForceUMDDelay) {
return IOTIMING_REALISTIC;
} else {
return g_Config.iIOTimingMethod;
}
}
static void TellFsThreadEnded (SceUID threadID) {
pspFileSystem.ThreadEnded(threadID);
}
@@ -339,7 +347,8 @@ static void __IoAsyncNotify(u64 userdata, int cyclesLate) {
return;
}
if (g_Config.iIOTimingMethod == IOTIMING_HOST) {
int ioTimingMethod = GetIOTimingMethod();
if (ioTimingMethod == IOTIMING_HOST) {
// Not all async operations actually queue up. Maybe should separate them?
if (!ioManager.HasResult(f->handle) && ioManager.HasOperation(f->handle)) {
// Try again in another 0.5ms until the IO completes on the host.
@@ -347,7 +356,7 @@ static void __IoAsyncNotify(u64 userdata, int cyclesLate) {
return;
}
__IoCompleteAsyncIO(f);
} else if (g_Config.iIOTimingMethod == IOTIMING_REALISTIC) {
} else if (ioTimingMethod == IOTIMING_REALISTIC) {
u64 finishTicks = __IoCompleteAsyncIO(f);
if (finishTicks > CoreTiming::GetTicks()) {
// Reschedule for later, since we now know how long it ought to take.
@@ -396,13 +405,14 @@ static void __IoSyncNotify(u64 userdata, int cyclesLate) {
return;
}
if (g_Config.iIOTimingMethod == IOTIMING_HOST) {
int ioTimingMethod = GetIOTimingMethod();
if (ioTimingMethod == IOTIMING_HOST) {
if (!ioManager.HasResult(f->handle)) {
// Try again in another 0.5ms until the IO completes on the host.
CoreTiming::ScheduleEvent(usToCycles(500) - cyclesLate, syncNotifyEvent, userdata);
return;
}
} else if (g_Config.iIOTimingMethod == IOTIMING_REALISTIC) {
} else if (ioTimingMethod == IOTIMING_REALISTIC) {
u64 finishTicks = ioManager.ResultFinishTicks(f->handle);
if (finishTicks > CoreTiming::GetTicks()) {
// Reschedule for later when the result should finish.
@@ -723,7 +733,8 @@ static u32 sceKernelStderr() {
u64 __IoCompleteAsyncIO(FileNode *f) {
PROFILE_THIS_SCOPE("io_rw");
if (g_Config.iIOTimingMethod == IOTIMING_REALISTIC) {
int ioTimingMethod = GetIOTimingMethod();
if (ioTimingMethod == IOTIMING_REALISTIC) {
u64 finishTicks = ioManager.ResultFinishTicks(f->handle);
if (finishTicks > CoreTiming::GetTicks()) {
return finishTicks;
@@ -921,7 +932,7 @@ static bool __IoRead(int &result, int id, u32 data_addr, int size, int &us) {
ioManager.ScheduleOperation(ev);
return false;
} else {
if (g_Config.iIOTimingMethod != IOTIMING_REALISTIC) {
if (GetIOTimingMethod() != IOTIMING_REALISTIC) {
result = (int) pspFileSystem.ReadFile(f->handle, data, size);
} else {
result = (int) pspFileSystem.ReadFile(f->handle, data, size, us);
@@ -991,7 +1002,7 @@ static u32 sceIoReadAsync(int id, u32 data_addr, int size) {
int us;
bool complete = __IoRead(result, id, data_addr, size, us);
if (complete) {
f->asyncResult = result;
f->asyncResult = (s64)result;
DEBUG_LOG(SCEIO, "%llx=sceIoReadAsync(%d, %08x, %x)", f->asyncResult, id, data_addr, size);
} else {
DEBUG_LOG(SCEIO, "sceIoReadAsync(%d, %08x, %x): deferring result", id, data_addr, size);
@@ -1056,7 +1067,7 @@ static bool __IoWrite(int &result, int id, u32 data_addr, int size, int &us) {
ioManager.ScheduleOperation(ev);
return false;
} else {
if (g_Config.iIOTimingMethod != IOTIMING_REALISTIC) {
if (GetIOTimingMethod() != IOTIMING_REALISTIC) {
result = (int) pspFileSystem.WriteFile(f->handle, (u8 *) data_ptr, size);
} else {
result = (int) pspFileSystem.WriteFile(f->handle, (u8 *) data_ptr, size, us);
@@ -1125,7 +1136,7 @@ static u32 sceIoWriteAsync(int id, u32 data_addr, int size) {
int us;
bool complete = __IoWrite(result, id, data_addr, size, us);
if (complete) {
f->asyncResult = result;
f->asyncResult = (s64)result;
DEBUG_LOG(SCEIO, "%llx=sceIoWriteAsync(%d, %08x, %x)", f->asyncResult, id, data_addr, size);
} else {
DEBUG_LOG(SCEIO, "sceIoWriteAsync(%d, %08x, %x): deferring result", id, data_addr, size);
@@ -1935,7 +1946,7 @@ static u32 sceIoOpenAsync(const char *filename, int flags, int mode)
f = new FileNode();
f->handle = kernelObjects.Create(f);
f->fullpath = filename;
f->asyncResult = error == 0 ? SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND : error;
f->asyncResult = error == 0 ? (s64)SCE_KERNEL_ERROR_ERRNO_FILE_NOT_FOUND : (s64)error;
f->closePending = true;
fd = __IoAllocFd(f);
+3 -1
View File
@@ -684,7 +684,9 @@ const HLEFunction Kernel_Library[] =
static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) {
ERROR_LOG(SCEKERNEL, "Untested sysclib_memcpy(dest=%08x, src=%08x, size=%i)", dst, src, size);
memcpy(Memory::GetPointer(dst), Memory::GetPointer(src), size);
if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) {
memcpy(Memory::GetPointer(dst), Memory::GetPointer(src), size);
}
return dst;
}
+3 -2
View File
@@ -84,13 +84,14 @@ enum {
};
// This is a workaround for misbehaving homebrew (like TBL's Suicide Barbie (Final)).
static const char *lieAboutSuccessModules[] = {
static const char * const lieAboutSuccessModules[] = {
"flash0:/kd/audiocodec.prx",
"flash0:/kd/audiocodec_260.prx",
"flash0:/kd/libatrac3plus.prx",
"disc0:/PSP_GAME/SYSDIR/UPDATE/EBOOT.BIN",
};
static const char *blacklistedModules[] = {
static const char * const blacklistedModules[] = {
"sceATRAC3plus_Library",
"sceFont_Library",
"SceFont_Library",
+1 -1
View File
@@ -1599,7 +1599,6 @@ static int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr)
Memory::Write_U32(1, attrAddr);
}
DEBUG_LOG(ME, "%x=sceMpegGetAvcAu(%08x, %08x, %08x, %08x)", result, mpeg, streamId, auAddr, attrAddr);
// TODO: sceMpegGetAvcAu seems to modify esSize, and delay when it's > 1000 or something.
// There's definitely more to it, but ultimately it seems games should expect it to delay randomly.
@@ -1664,6 +1663,7 @@ static int sceMpegGetAtracAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr)
// Instead, let's abuse it to keep track of the stream number.
if (streamInfo != ctx->streamMap.end()) {
atracAu.esBuffer = streamInfo->second.num;
ctx->mediaengine->setAudioStream(streamInfo->second.num);
}
int result = 0;
+1 -1
View File
@@ -49,7 +49,7 @@ static const int PSMF_AUDIO_STREAM_ID = 0xBD;
struct SceMpegAu {
s64_le pts; // presentation time stamp
s64_le dts; // decode time stamp
u32_le esBuffer;
u32_le esBuffer; // WARNING: We abuse this to keep track of the stream number!
u32_le esSize;
void read(u32 addr);
+1 -2
View File
@@ -22,8 +22,7 @@ void Register_sceUsbGps();
void __UsbGpsInit();
void __UsbGpsDoState(PointerWrap &p);
#pragma pack(push)
#pragma pack(1)
#pragma pack(push, 1)
typedef struct {
short year;
+9 -2
View File
@@ -26,6 +26,7 @@
#include "Core/MIPS/MIPS.h"
#include "Core/Reporting.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "Core/HLE/sceKernel.h"
#include "Core/HLE/sceKernelMemory.h"
@@ -185,8 +186,14 @@ static int sceUtilitySavedataInitStart(u32 paramAddr)
{
if (currentDialogActive && currentDialogType != UTILITY_DIALOG_SAVEDATA)
{
WARN_LOG(SCEUTILITY, "sceUtilitySavedataInitStart(%08x): wrong dialog type", paramAddr);
return SCE_ERROR_UTILITY_WRONG_TYPE;
if (PSP_CoreParameter().compat.flags().YugiohSaveFix)
{
WARN_LOG(SCEUTILITY, "Yugioh Savedata Correction");
}
else {
WARN_LOG(SCEUTILITY, "sceUtilitySavedataInitStart(%08x): wrong dialog type", paramAddr);
return SCE_ERROR_UTILITY_WRONG_TYPE;
}
}
oldStatus = 100;
+3 -1
View File
@@ -294,7 +294,9 @@ bool LoadFile(FileLoader **fileLoaderPtr, std::string *error_string) {
case IdentifiedFileType::ERROR_IDENTIFYING:
ERROR_LOG(LOADER, "Could not read file");
*error_string = "Error reading file";
*error_string = fileLoader ? fileLoader->LatestError() : "";
if (error_string->empty())
*error_string = "Error reading file";
break;
case IdentifiedFileType::ARCHIVE_RAR:
+42
View File
@@ -93,6 +93,48 @@ public:
// Cancel any operations that might block, if possible.
virtual void Cancel() {
}
virtual std::string LatestError() const {
return "";
}
};
class ProxiedFileLoader : public FileLoader {
public:
ProxiedFileLoader(FileLoader *backend) : backend_(backend) {
}
~ProxiedFileLoader() override {
// Takes ownership.
delete backend_;
}
bool IsRemote() override {
return backend_->IsRemote();
}
bool Exists() override {
return backend_->Exists();
}
bool ExistsFast() override {
return backend_->ExistsFast();
}
bool IsDirectory() override {
return backend_->IsDirectory();
}
s64 FileSize() override {
return backend_->FileSize();
}
std::string Path() const override {
return backend_->Path();
}
void Cancel() override {
backend_->Cancel();
}
std::string LatestError() const override {
return backend_->LatestError();
}
protected:
FileLoader *backend_;
};
inline u32 operator & (const FileLoader::Flags &a, const FileLoader::Flags &b) {
+9 -9
View File
@@ -43,7 +43,7 @@ using namespace MIPSAnalyst;
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp
@@ -72,7 +72,7 @@ namespace MIPSComp
void ArmJit::Comp_IType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_IMM);
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
u32 uimm = op & 0xFFFF;
u32 suimm = (u32)(s32)simm;
@@ -150,7 +150,7 @@ namespace MIPSComp
void ArmJit::Comp_RType2(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
@@ -234,7 +234,7 @@ namespace MIPSComp
void ArmJit::Comp_RType3(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
@@ -502,7 +502,7 @@ namespace MIPSComp
void ArmJit::Comp_ShiftType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU);
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
int fd = _FD;
@@ -529,7 +529,7 @@ namespace MIPSComp
void ArmJit::Comp_Special3(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rt = _RT;
@@ -591,7 +591,7 @@ namespace MIPSComp
void ArmJit::Comp_Allegrex(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
@@ -645,7 +645,7 @@ namespace MIPSComp
void ArmJit::Comp_Allegrex2(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
@@ -677,7 +677,7 @@ namespace MIPSComp
void ArmJit::Comp_MulDivType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(MULDIV);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
+6 -6
View File
@@ -44,7 +44,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp
@@ -54,7 +54,7 @@ namespace MIPSComp
void ArmJit::Comp_FPU3op(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
int ft = _FT;
int fs = _FS;
@@ -92,7 +92,7 @@ extern int logBlocks;
void ArmJit::Comp_FPULS(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_FPU);
CheckMemoryBreakpoint();
s32 offset = (s16)(op & 0xFFFF);
@@ -193,7 +193,7 @@ void ArmJit::Comp_FPULS(MIPSOpcode op)
}
void ArmJit::Comp_FPUComp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_COMP);
int opc = op & 0xF;
if (opc >= 8) opc -= 8; // alias
@@ -258,7 +258,7 @@ void ArmJit::Comp_FPUComp(MIPSOpcode op) {
}
void ArmJit::Comp_FPU2op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
int fs = _FS;
int fd = _FD;
@@ -350,7 +350,7 @@ void ArmJit::Comp_FPU2op(MIPSOpcode op) {
void ArmJit::Comp_mxc1(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_XFER);
int fs = _FS;
MIPSGPReg rt = _RT;
+4 -4
View File
@@ -42,7 +42,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp
@@ -111,14 +111,14 @@ namespace MIPSComp
}
void ArmJit::Comp_ITypeMemLR(MIPSOpcode op, bool load) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
CheckMemoryBreakpoint();
int offset = (signed short)(op & 0xFFFF);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
int o = op >> 26;
if (!js.inDelaySlot) {
if (!js.inDelaySlot && !jo.Disabled(JitDisable::LSU_UNALIGNED)) {
// Optimisation: Combine to single unaligned load/store
bool isLeft = (o == 34 || o == 42);
CheckMemoryBreakpoint(1);
@@ -260,7 +260,7 @@ namespace MIPSComp
void ArmJit::Comp_ITypeMem(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
CheckMemoryBreakpoint();
int offset = (signed short)(op&0xFFFF);
bool load = false;
+33 -33
View File
@@ -40,7 +40,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
#define NEON_IF_AVAILABLE(func) { if (jo.useNEONVFPU) { func(op); return; } }
@@ -87,7 +87,7 @@ namespace MIPSComp
void ArmJit::Comp_VPFX(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int data = op & 0xFFFFF;
int regnum = (op >> 24) & 3;
switch (regnum) {
@@ -225,7 +225,7 @@ namespace MIPSComp
void ArmJit::Comp_SV(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_SV);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
CheckMemoryBreakpoint();
s32 offset = (signed short)(op & 0xFFFC);
@@ -332,7 +332,7 @@ namespace MIPSComp
void ArmJit::Comp_SVQ(MIPSOpcode op)
{
NEON_IF_AVAILABLE(CompNEON_SVQ);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
CheckMemoryBreakpoint();
int imm = (signed short)(op&0xFFFC);
@@ -478,7 +478,7 @@ namespace MIPSComp
void ArmJit::Comp_VVectorInit(MIPSOpcode op)
{
NEON_IF_AVAILABLE(CompNEON_VVectorInit);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
// WARNING: No prefix support!
if (js.HasUnknownPrefix()) {
DISABLE;
@@ -515,7 +515,7 @@ namespace MIPSComp
void ArmJit::Comp_VIdt(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VIdt);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -553,7 +553,7 @@ namespace MIPSComp
void ArmJit::Comp_VMatrixInit(MIPSOpcode op)
{
NEON_IF_AVAILABLE(CompNEON_VMatrixInit);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
// Don't think matrix init ops care about prefixes.
// DISABLE;
@@ -601,7 +601,7 @@ namespace MIPSComp
void ArmJit::Comp_VHdp(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VHdp);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -644,7 +644,7 @@ namespace MIPSComp
void ArmJit::Comp_Vhoriz(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vhoriz);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -687,7 +687,7 @@ namespace MIPSComp
void ArmJit::Comp_VDot(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VDot);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -724,7 +724,7 @@ namespace MIPSComp
void ArmJit::Comp_VecDo3(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VecDo3);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -884,7 +884,7 @@ namespace MIPSComp
void ArmJit::Comp_VV2Op(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VV2Op);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1077,7 +1077,7 @@ namespace MIPSComp
void ArmJit::Comp_Vi2f(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vi2f);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1124,7 +1124,7 @@ namespace MIPSComp
void ArmJit::Comp_Vh2f(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vh2f);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1186,7 +1186,7 @@ namespace MIPSComp
void ArmJit::Comp_Vf2i(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vf2i);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
@@ -1256,7 +1256,7 @@ namespace MIPSComp
void ArmJit::Comp_Mftv(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Mftv);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int imm = op & 0xFF;
MIPSGPReg rt = _RT;
@@ -1331,7 +1331,7 @@ namespace MIPSComp
void ArmJit::Comp_Vmfvc(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vmtvc);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
@@ -1350,7 +1350,7 @@ namespace MIPSComp
void ArmJit::Comp_Vmtvc(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vmtvc);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
@@ -1377,7 +1377,7 @@ namespace MIPSComp
void ArmJit::Comp_Vmmov(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vmmov);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// This probably ignores prefixes for all sane intents and purposes.
if (_VS == _VD) {
@@ -1415,7 +1415,7 @@ namespace MIPSComp
void ArmJit::Comp_VScl(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VScl);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1464,7 +1464,7 @@ namespace MIPSComp
}
void ArmJit::Comp_Vmmul(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1513,7 +1513,7 @@ namespace MIPSComp
void ArmJit::Comp_Vtfm(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vtfm);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1584,7 +1584,7 @@ namespace MIPSComp
void ArmJit::Comp_Vi2x(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vi2x);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1662,7 +1662,7 @@ namespace MIPSComp
void ArmJit::Comp_Vx2i(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vx2i);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1751,7 +1751,7 @@ namespace MIPSComp
void ArmJit::Comp_VCrossQuat(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VCrossQuat);
// This op does not support prefixes anyway.
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1831,7 +1831,7 @@ namespace MIPSComp
void ArmJit::Comp_Vcmp(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vcmp);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix())
DISABLE;
@@ -2019,7 +2019,7 @@ namespace MIPSComp
void ArmJit::Comp_Vcmov(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vcmov);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -2070,7 +2070,7 @@ namespace MIPSComp
void ArmJit::Comp_Viim(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Viim);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -2088,7 +2088,7 @@ namespace MIPSComp
void ArmJit::Comp_Vfim(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vfim);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -2108,7 +2108,7 @@ namespace MIPSComp
void ArmJit::Comp_Vcst(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vcst);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -2178,7 +2178,7 @@ namespace MIPSComp
void ArmJit::Comp_VRot(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_VRot);
// VRot probably doesn't accept prefixes anyway.
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -2244,7 +2244,7 @@ namespace MIPSComp
void ArmJit::Comp_Vsgn(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vsgn);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -2293,7 +2293,7 @@ namespace MIPSComp
void ArmJit::Comp_Vocp(MIPSOpcode op) {
NEON_IF_AVAILABLE(CompNEON_Vocp);
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
+28 -27
View File
@@ -53,7 +53,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
#define DISABLE_UNKNOWN_PREFIX { WLOG("DISABLE: Unknown Prefix in %s", __FUNCTION__); fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
@@ -82,7 +82,7 @@ static const float zero = 0.0f;
void ArmJit::CompNEON_VecDo3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -158,7 +158,7 @@ void ArmJit::CompNEON_VecDo3(MIPSOpcode op) {
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
void ArmJit::CompNEON_SV(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
CheckMemoryBreakpoint();
// Remember to use single lane stores here and not VLDR/VSTR - switching usage
@@ -276,7 +276,7 @@ inline int MIPS_GET_VQVT(u32 op) {
}
void ArmJit::CompNEON_SVQ(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
CheckMemoryBreakpoint();
int offset = (signed short)(op & 0xFFFC);
@@ -425,7 +425,7 @@ void ArmJit::CompNEON_SVQ(MIPSOpcode op) {
}
void ArmJit::CompNEON_VVectorInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
// WARNING: No prefix support!
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
@@ -450,7 +450,7 @@ void ArmJit::CompNEON_VVectorInit(MIPSOpcode op) {
}
void ArmJit::CompNEON_VDot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -484,7 +484,7 @@ void ArmJit::CompNEON_VDot(MIPSOpcode op) {
void ArmJit::CompNEON_VHdp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -496,7 +496,7 @@ void ArmJit::CompNEON_VHdp(MIPSOpcode op) {
}
void ArmJit::CompNEON_VScl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -515,7 +515,7 @@ void ArmJit::CompNEON_VScl(MIPSOpcode op) {
}
void ArmJit::CompNEON_VV2Op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -666,7 +666,7 @@ void ArmJit::CompNEON_VV2Op(MIPSOpcode op) {
}
void ArmJit::CompNEON_Mftv(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int imm = op & 0xFF;
MIPSGPReg rt = _RT;
switch ((op >> 21) & 0x1f) {
@@ -746,7 +746,7 @@ void ArmJit::CompNEON_Vmfvc(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vmtvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
@@ -767,7 +767,7 @@ void ArmJit::CompNEON_Vmtvc(MIPSOpcode op) {
}
void ArmJit::CompNEON_VMatrixInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
MatrixSize msz = GetMtxSize(op);
int n = GetMatrixSide(msz);
@@ -828,7 +828,7 @@ void ArmJit::CompNEON_VMatrixInit(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vmmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
if (_VS == _VD) {
// A lot of these no-op matrix moves in Wipeout... Just drop the instruction entirely.
return;
@@ -856,7 +856,7 @@ void ArmJit::CompNEON_Vmmov(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vmmul(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
MatrixSize msz = GetMtxSize(op);
int n = GetMatrixSide(msz);
@@ -895,7 +895,7 @@ void ArmJit::CompNEON_Vmmul(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vmscl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
MatrixSize msz = GetMtxSize(op);
@@ -920,7 +920,7 @@ void ArmJit::CompNEON_Vmscl(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vtfm(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -986,7 +986,7 @@ void ArmJit::CompNEON_Vf2i(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vi2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1012,6 +1012,7 @@ void ArmJit::CompNEON_Vi2f(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vh2f(MIPSOpcode op) {
CONDITIONAL_DISABLE(VFPU_VEC);
if (!cpu_info.bHalf) {
// No hardware support for half-to-float, fallback to interpreter
// TODO: Translate the fast SSE solution to standard integer/VFP stuff
@@ -1045,7 +1046,7 @@ void ArmJit::CompNEON_Vh2f(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vcst(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -1063,7 +1064,7 @@ void ArmJit::CompNEON_Vcst(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vhoriz(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -1102,7 +1103,7 @@ void ArmJit::CompNEON_Vhoriz(MIPSOpcode op) {
}
void ArmJit::CompNEON_VRot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
@@ -1121,7 +1122,7 @@ void ArmJit::CompNEON_VRot(MIPSOpcode op) {
}
void ArmJit::CompNEON_VIdt(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -1167,7 +1168,7 @@ void ArmJit::CompNEON_VIdt(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vcmp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1298,7 +1299,7 @@ void ArmJit::CompNEON_Vcmp(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vcmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1341,7 +1342,7 @@ void ArmJit::CompNEON_Vcmov(MIPSOpcode op) {
}
void ArmJit::CompNEON_Viim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1358,7 +1359,7 @@ void ArmJit::CompNEON_Viim(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vfim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1379,7 +1380,7 @@ void ArmJit::CompNEON_Vfim(MIPSOpcode op) {
// https://code.google.com/p/bullet/source/browse/branches/PhysicsEffects/include/vecmath/neon/vectormath_neon_assembly_implementations.S?r=2488
void ArmJit::CompNEON_VCrossQuat(MIPSOpcode op) {
// This op does not support prefixes anyway.
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE_UNKNOWN_PREFIX;
}
@@ -1427,7 +1428,7 @@ void ArmJit::CompNEON_Vsgn(MIPSOpcode op) {
}
void ArmJit::CompNEON_Vocp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
+1 -1
View File
@@ -46,7 +46,7 @@
using namespace ArmJitConstants;
static void DisassembleArm(const u8 *data, int size) {
void DisassembleArm(const u8 *data, int size) {
char temp[256];
for (int i = 0; i < size; i += 4) {
const u32 *codePtr = (const u32 *)(data + i);
+9 -9
View File
@@ -44,7 +44,7 @@ using namespace MIPSAnalyst;
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp {
@@ -70,7 +70,7 @@ void Arm64Jit::CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARM64XEm
}
void Arm64Jit::Comp_IType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_IMM);
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
u32 uimm = op & 0xFFFF;
u32 suimm = (u32)(s32)simm;
@@ -146,7 +146,7 @@ void Arm64Jit::Comp_IType(MIPSOpcode op) {
}
void Arm64Jit::Comp_RType2(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
@@ -234,7 +234,7 @@ void Arm64Jit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARM64XE
}
void Arm64Jit::Comp_RType3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@@ -406,7 +406,7 @@ void Arm64Jit::CompShiftVar(MIPSOpcode op, Arm64Gen::ShiftType shiftType) {
}
void Arm64Jit::Comp_ShiftType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU);
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
int fd = _FD;
@@ -431,7 +431,7 @@ void Arm64Jit::Comp_ShiftType(MIPSOpcode op) {
}
void Arm64Jit::Comp_Special3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rt = _RT;
@@ -479,7 +479,7 @@ void Arm64Jit::Comp_Special3(MIPSOpcode op) {
}
void Arm64Jit::Comp_Allegrex(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
@@ -529,7 +529,7 @@ void Arm64Jit::Comp_Allegrex(MIPSOpcode op) {
}
void Arm64Jit::Comp_Allegrex2(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
@@ -560,7 +560,7 @@ void Arm64Jit::Comp_Allegrex2(MIPSOpcode op) {
}
void Arm64Jit::Comp_MulDivType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(MULDIV);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
+6 -6
View File
@@ -52,7 +52,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp {
@@ -60,7 +60,7 @@ namespace MIPSComp {
using namespace Arm64JitConstants;
void Arm64Jit::Comp_FPU3op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
int ft = _FT;
int fs = _FS;
@@ -80,7 +80,7 @@ void Arm64Jit::Comp_FPU3op(MIPSOpcode op) {
void Arm64Jit::Comp_FPULS(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_FPU);
CheckMemoryBreakpoint();
// Surprisingly, these work fine alraedy.
@@ -152,7 +152,7 @@ void Arm64Jit::Comp_FPULS(MIPSOpcode op)
}
void Arm64Jit::Comp_FPUComp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_COMP);
int opc = op & 0xF;
if (opc >= 8) opc -= 8; // alias
@@ -198,7 +198,7 @@ void Arm64Jit::Comp_FPUComp(MIPSOpcode op) {
}
void Arm64Jit::Comp_FPU2op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
int fs = _FS;
int fd = _FD;
@@ -301,7 +301,7 @@ void Arm64Jit::Comp_FPU2op(MIPSOpcode op) {
void Arm64Jit::Comp_mxc1(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_XFER);
int fs = _FS;
MIPSGPReg rt = _RT;
+4 -4
View File
@@ -42,7 +42,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp {
@@ -110,14 +110,14 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_ITypeMemLR(MIPSOpcode op, bool load) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
CheckMemoryBreakpoint();
int offset = (signed short)(op & 0xFFFF);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
int o = op >> 26;
if (!js.inDelaySlot) {
if (!js.inDelaySlot && !jo.Disabled(JitDisable::LSU_UNALIGNED)) {
// Optimisation: Combine to single unaligned load/store
bool isLeft = (o == 34 || o == 42);
CheckMemoryBreakpoint(1);
@@ -256,7 +256,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_ITypeMem(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
CheckMemoryBreakpoint();
int offset = (signed short)(op & 0xFFFF);
+31 -30
View File
@@ -38,7 +38,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { fpr.ReleaseSpillLocksAndDiscardTemps(); Comp_Generic(op); return; }
#define _RS MIPS_GET_RS(op)
@@ -80,7 +80,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VPFX(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int data = op & 0xFFFFF;
int regnum = (op >> 24) & 3;
switch (regnum) {
@@ -201,7 +201,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_SV(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
CheckMemoryBreakpoint();
s32 offset = (signed short)(op & 0xFFFC);
@@ -275,7 +275,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_SVQ(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
CheckMemoryBreakpoint();
int imm = (signed short)(op&0xFFFC);
@@ -359,7 +359,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VVectorInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
// WARNING: No prefix support!
if (js.HasUnknownPrefix()) {
DISABLE;
@@ -393,7 +393,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VIdt(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -428,7 +428,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VMatrixInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
// Don't think matrix init ops care about prefixes.
// DISABLE;
@@ -475,7 +475,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VHdp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -517,7 +517,7 @@ namespace MIPSComp {
alignas(16) static const float vavg_table[4] = { 1.0f, 1.0f / 2.0f, 1.0f / 3.0f, 1.0f / 4.0f };
void Arm64Jit::Comp_Vhoriz(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -559,7 +559,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VDot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -595,7 +595,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VecDo3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -744,7 +744,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VV2Op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -884,7 +884,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vi2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -931,7 +931,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vh2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -978,6 +978,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Mftv(MIPSOpcode op) {
CONDITIONAL_DISABLE(VFPU_XFER);
int imm = op & 0xFF;
MIPSGPReg rt = _RT;
switch ((op >> 21) & 0x1f) {
@@ -1063,7 +1064,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vmfvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
@@ -1081,7 +1082,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vmtvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
@@ -1107,7 +1108,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vmmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// This probably ignores prefixes for all sane intents and purposes.
if (_VS == _VD) {
@@ -1144,7 +1145,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_VScl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1193,7 +1194,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vmmul(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1239,7 +1240,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vtfm(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1307,7 +1308,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vi2x(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1376,7 +1377,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vx2i(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1471,7 +1472,7 @@ namespace MIPSComp {
void Arm64Jit::Comp_VCrossQuat(MIPSOpcode op) {
// This op does not support prefixes anyway.
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1550,7 +1551,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vcmp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1727,7 +1728,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vcmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1778,7 +1779,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Viim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1795,7 +1796,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vfim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1814,7 +1815,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vcst(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1882,7 +1883,7 @@ namespace MIPSComp {
// calling the math library.
void Arm64Jit::Comp_VRot(MIPSOpcode op) {
// VRot probably doesn't accept prefixes anyway.
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1943,7 +1944,7 @@ namespace MIPSComp {
}
void Arm64Jit::Comp_Vocp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
+9 -9
View File
@@ -38,14 +38,14 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (opts.disableFlags & (uint32_t)JitDisable::flag) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
#define INVALIDOP { Comp_Generic(op); return; }
namespace MIPSComp {
void IRFrontend::Comp_IType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_IMM);
s32 simm = (s32)_IMM16; // sign extension
u32 uimm = (u16)_IMM16;
@@ -87,7 +87,7 @@ void IRFrontend::Comp_IType(MIPSOpcode op) {
}
void IRFrontend::Comp_RType2(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
@@ -111,7 +111,7 @@ void IRFrontend::Comp_RType2(MIPSOpcode op) {
}
void IRFrontend::Comp_RType3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@@ -197,7 +197,7 @@ void IRFrontend::CompShiftVar(MIPSOpcode op, IROp shiftOp) {
}
void IRFrontend::Comp_ShiftType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU);
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
int sa = _SA;
@@ -222,7 +222,7 @@ void IRFrontend::Comp_ShiftType(MIPSOpcode op) {
}
void IRFrontend::Comp_Special3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rt = _RT;
@@ -265,7 +265,7 @@ void IRFrontend::Comp_Special3(MIPSOpcode op) {
void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
@@ -293,7 +293,7 @@ void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
}
void IRFrontend::Comp_Allegrex2(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
@@ -315,7 +315,7 @@ void IRFrontend::Comp_Allegrex2(MIPSOpcode op) {
}
void IRFrontend::Comp_MulDivType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(MULDIV);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
+6 -6
View File
@@ -49,14 +49,14 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (opts.disableFlags & (uint32_t)JitDisable::flag) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
#define INVALIDOP { Comp_Generic(op); return; }
namespace MIPSComp {
void IRFrontend::Comp_FPU3op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
int ft = _FT;
int fs = _FS;
@@ -74,7 +74,7 @@ void IRFrontend::Comp_FPU3op(MIPSOpcode op) {
}
void IRFrontend::Comp_FPULS(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_FPU);
s32 offset = _IMM16;
int ft = _FT;
MIPSGPReg rs = _RS;
@@ -97,7 +97,7 @@ void IRFrontend::Comp_FPULS(MIPSOpcode op) {
}
void IRFrontend::Comp_FPUComp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_COMP);
int opc = op & 0xF;
if (opc >= 8) opc -= 8; // alias
@@ -139,7 +139,7 @@ void IRFrontend::Comp_FPUComp(MIPSOpcode op) {
}
void IRFrontend::Comp_FPU2op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
int fs = _FS;
int fd = _FD;
@@ -185,7 +185,7 @@ void IRFrontend::Comp_FPU2op(MIPSOpcode op) {
}
void IRFrontend::Comp_mxc1(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_XFER);
int fs = _FS;
MIPSGPReg rt = _RT;
+3 -3
View File
@@ -39,13 +39,13 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (opts.disableFlags & (uint32_t)JitDisable::flag) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
#define INVALIDOP { Comp_Generic(op); return; }
namespace MIPSComp {
void IRFrontend::Comp_ITypeMem(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
int offset = _IMM16;
MIPSGPReg rt = _RT;
@@ -106,7 +106,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Cache(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
// int imm = (s16)(op & 0xFFFF);
// int rs = _RS;
+38 -38
View File
@@ -35,7 +35,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (opts.disableFlags & (uint32_t)JitDisable::flag) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
#define INVALIDOP { Comp_Generic(op); return; }
@@ -109,7 +109,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VPFX(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int data = op & 0xFFFFF;
int regnum = (op >> 24) & 3;
switch (regnum) {
@@ -274,7 +274,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_SV(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
s32 offset = (signed short)(op & 0xFFFC);
int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5);
MIPSGPReg rs = _RS;
@@ -296,7 +296,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_SVQ(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
int imm = (signed short)(op & 0xFFFC);
int vt = (((op >> 16) & 0x1f)) | ((op & 1) << 5);
MIPSGPReg rs = _RS;
@@ -342,7 +342,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VVectorInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -368,7 +368,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VIdt(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -406,7 +406,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VMatrixInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
MatrixSize sz = GetMtxSize(op);
if (sz != M_4x4) {
DISABLE;
@@ -447,7 +447,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VHdp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -487,7 +487,7 @@ namespace MIPSComp {
alignas(16) static const float vavg_table[4] = { 1.0f, 1.0f / 2.0f, 1.0f / 3.0f, 1.0f / 4.0f };
void IRFrontend::Comp_Vhoriz(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -524,7 +524,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VDot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -562,7 +562,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VecDo3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -721,7 +721,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VV2Op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -847,7 +847,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vi2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -894,7 +894,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vh2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
// Vector expand half to float
// d[N*2] = float(lowerhalf(s[N])), d[N*2+1] = float(upperhalf(s[N]))
@@ -903,7 +903,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vf2i(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
// Vector float to integer
// d[N] = int(S[N] * mult)
@@ -913,7 +913,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Mftv(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int imm = op & 0xFF;
MIPSGPReg rt = _RT;
@@ -966,7 +966,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vmfvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
// Vector Move from vector control reg (no prefixes)
// S[0] = VFPU_CTRL[i]
@@ -982,7 +982,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vmtvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
// Vector Move to vector control reg (no prefixes)
// VFPU_CTRL[i] = S[0]
@@ -1004,7 +1004,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vmmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// Matrix move (no prefixes)
// D[N,M] = S[N,M]
@@ -1061,7 +1061,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vmscl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// Matrix scale, matrix by scalar (no prefixes)
// d[N,M] = s[N,M] * t[0]
@@ -1099,7 +1099,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VScl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1173,7 +1173,7 @@ namespace MIPSComp {
// This may or may not be a win when using the IR interpreter...
// Many more instructions to interpret.
void IRFrontend::Comp_Vmmul(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// Matrix multiply (no prefixes)
// D[0 .. N,0 .. M] = S[0 .. N, 0 .. M] * T[0 .. N,0 .. M]
@@ -1256,7 +1256,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vtfm(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// Vertex transform, vector by matrix (no prefixes)
// d[N] = s[N*m .. N*m + n-1] dot t[0 .. n-1]
@@ -1358,7 +1358,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VCrs(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1372,7 +1372,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VDet(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1385,7 +1385,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vi2x(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1470,7 +1470,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vx2i(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1570,7 +1570,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_VCrossQuat(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
// TODO: Does this instruction even look at prefixes at all?
if (js.HasUnknownPrefix())
DISABLE;
@@ -1627,7 +1627,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vcmp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1651,7 +1651,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vcmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1690,7 +1690,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Viim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1705,7 +1705,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vfim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1723,7 +1723,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vcst(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1747,7 +1747,7 @@ namespace MIPSComp {
// Very heavily used by FF:CC. Should be replaced by a fast approximation instead of
// calling the math library.
void IRFrontend::Comp_VRot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (!js.HasNoPrefix()) {
// Prefixes work strangely for this:
// * They never apply to cos (whether d or s prefixes.)
@@ -1797,7 +1797,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vsgn(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1835,7 +1835,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vocp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -1872,7 +1872,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_ColorConv(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1883,7 +1883,7 @@ namespace MIPSComp {
}
void IRFrontend::Comp_Vbfy(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
+1
View File
@@ -369,6 +369,7 @@ private:
};
struct IROptions {
uint32_t disableFlags;
bool unalignedLoadStore;
};
+2 -1
View File
@@ -44,7 +44,8 @@ IRJit::IRJit(MIPSState *mips) : frontend_(mips->HasDefaultPrefix()), mips_(mips)
InitIR();
IROptions opts{};
opts.unalignedLoadStore = true;
opts.disableFlags = g_Config.uJitDisableFlags;
opts.unalignedLoadStore = opts.disableFlags & (uint32_t)JitDisable::LSU_UNALIGNED;
frontend_.SetOptions(opts);
}
+14 -7
View File
@@ -16,35 +16,38 @@
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#include "Common/CPUDetect.h"
#include "Core/Config.h"
#include "Core/MIPS/JitCommon/JitState.h"
#include "Common/MemoryUtil.h"
namespace MIPSComp {
JitOptions::JitOptions() {
disableFlags = g_Config.uJitDisableFlags;
// x86
enableVFPUSIMD = true;
enableVFPUSIMD = !Disabled(JitDisable::SIMD);
// Set by Asm if needed.
reserveR15ForAsm = false;
// ARM/ARM64
useBackJump = false;
useForwardJump = false;
cachePointers = true;
cachePointers = !Disabled(JitDisable::CACHE_POINTERS);
// ARM only
downcountInRegister = true;
useNEONVFPU = false; // true
if (!cpu_info.bNEON)
if (!cpu_info.bNEON || Disabled(JitDisable::SIMD))
useNEONVFPU = false;
//ARM64
useASIMDVFPU = false; // true
useASIMDVFPU = false; // !Disabled(JitDisable::SIMD);
// Common
// We can get block linking to work with W^X by doing even more unprotect/re-protect, but let's try without first.
// enableBlocklink = !PlatformIsWXExclusive(); // Revert to this line if block linking is slow in W^X mode
enableBlocklink = true;
enableBlocklink = !Disabled(JitDisable::BLOCKLINK);
immBranches = false;
continueBranches = false;
continueJumps = false;
@@ -53,9 +56,13 @@ namespace MIPSComp {
useStaticAlloc = false;
enablePointerify = false;
#if PPSSPP_ARCH(ARM64)
useStaticAlloc = true;
useStaticAlloc = !Disabled(JitDisable::STATIC_ALLOC);
// iOS/etc. may disable at runtime if Memory::base is not nicely aligned.
enablePointerify = true;
enablePointerify = !Disabled(JitDisable::POINTERIFY);
#endif
}
bool JitOptions::Disabled(JitDisable bit) {
return (disableFlags & (uint32_t)bit) != 0;
}
}
+33
View File
@@ -173,9 +173,42 @@ namespace MIPSComp {
}
};
enum class JitDisable {
ALU = 0x0001,
ALU_IMM = 0x0002,
ALU_BIT = 0x0004,
MULDIV = 0x0008,
FPU = 0x0010,
FPU_COMP = 0x0040,
FPU_XFER = 0x0080,
VFPU_VEC = 0x0100,
VFPU_MTX = 0x0200,
VFPU_COMP = 0x0400,
VFPU_XFER = 0x0800,
LSU = 0x1000,
LSU_UNALIGNED = 0x2000,
LSU_FPU = 0x4000,
LSU_VFPU = 0x8000,
SIMD = 0x00100000,
BLOCKLINK = 0x00200000,
POINTERIFY = 0x00400000,
STATIC_ALLOC = 0x00800000,
CACHE_POINTERS = 0x01000000,
ALL_FLAGS = 0x01FFFFFF,
};
struct JitOptions {
JitOptions();
bool Disabled(JitDisable bit);
uint32_t disableFlags;
// x86
bool enableVFPUSIMD;
bool reserveR15ForAsm;
+1 -1
View File
@@ -1531,7 +1531,7 @@ skip:
}
// lw, sh, ...
if ((opInfo & IN_MEM) || (opInfo & OUT_MEM)) {
if (!IsSyscall(op) && (opInfo & (IN_MEM | OUT_MEM)) != 0) {
info.isDataAccess = true;
switch (opInfo & MEMTYPE_MASK) {
case MEMTYPE_BYTE:
+10 -10
View File
@@ -40,8 +40,8 @@ using namespace MIPSAnalyst;
// All functions should have CONDITIONAL_DISABLE, so we can narrow things down to a file quickly.
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
// #define CONDITIONAL_DISABLE(ignore) { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp
@@ -74,7 +74,7 @@ namespace MIPSComp
void Jit::Comp_IType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_IMM);
s32 simm = (s32)_IMM16; // sign extension
u32 uimm = op & 0xFFFF;
u32 suimm = (u32)(s32)simm;
@@ -197,7 +197,7 @@ namespace MIPSComp
void Jit::Comp_RType2(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
@@ -378,7 +378,7 @@ namespace MIPSComp
void Jit::Comp_RType3(MIPSOpcode op)
{
CONDITIONAL_DISABLE
CONDITIONAL_DISABLE(ALU);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@@ -668,7 +668,7 @@ namespace MIPSComp
void Jit::Comp_ShiftType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU);
int rs = (op>>21) & 0x1F;
MIPSGPReg rd = _RD;
int fd = (op>>6) & 0x1F;
@@ -696,7 +696,7 @@ namespace MIPSComp
void Jit::Comp_Special3(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rs = _RS;
MIPSGPReg rt = _RT;
@@ -786,7 +786,7 @@ namespace MIPSComp
void Jit::Comp_Allegrex(MIPSOpcode op)
{
CONDITIONAL_DISABLE
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
@@ -894,7 +894,7 @@ namespace MIPSComp
void Jit::Comp_Allegrex2(MIPSOpcode op)
{
CONDITIONAL_DISABLE
CONDITIONAL_DISABLE(ALU_BIT);
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
// Don't change $zr.
@@ -938,7 +938,7 @@ namespace MIPSComp
void Jit::Comp_MulDivType(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(MULDIV);
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
+6 -6
View File
@@ -42,7 +42,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp {
@@ -86,7 +86,7 @@ void Jit::CompFPTriArith(MIPSOpcode op, void (XEmitter::*arith)(X64Reg reg, OpAr
}
void Jit::Comp_FPU3op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
switch (op & 0x3f) {
case 0: CompFPTriArith(op, &XEmitter::ADDSS, false); break; //F(fd) = F(fs) + F(ft); //add
case 1: CompFPTriArith(op, &XEmitter::SUBSS, true); break; //F(fd) = F(fs) - F(ft); //sub
@@ -99,7 +99,7 @@ void Jit::Comp_FPU3op(MIPSOpcode op) {
}
void Jit::Comp_FPULS(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_FPU);
s32 offset = _IMM16;
int ft = _FT;
MIPSGPReg rs = _RS;
@@ -174,7 +174,7 @@ void Jit::CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN) {
}
void Jit::Comp_FPUComp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_COMP);
int fs = _FS;
int ft = _FT;
@@ -226,7 +226,7 @@ void Jit::Comp_FPUComp(MIPSOpcode op) {
}
void Jit::Comp_FPU2op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU);
int fs = _FS;
int fd = _FD;
@@ -355,7 +355,7 @@ void Jit::Comp_FPU2op(MIPSOpcode op) {
}
void Jit::Comp_mxc1(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(FPU_XFER);
int fs = _FS;
MIPSGPReg rt = _RT;
+10 -10
View File
@@ -42,7 +42,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp {
@@ -50,7 +50,7 @@ namespace MIPSComp {
void Jit::CompITypeMemRead(MIPSOpcode op, u32 bits, void (XEmitter::*mov)(int, int, X64Reg, OpArg), const void *safeFunc)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
int offset = _IMM16;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@@ -81,7 +81,7 @@ namespace MIPSComp {
void Jit::CompITypeMemWrite(MIPSOpcode op, u32 bits, const void *safeFunc)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
int offset = _IMM16;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@@ -137,7 +137,7 @@ namespace MIPSComp {
void Jit::CompITypeMemUnpairedLR(MIPSOpcode op, bool isStore)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
int o = op>>26;
int offset = _IMM16;
MIPSGPReg rt = _RT;
@@ -193,7 +193,7 @@ namespace MIPSComp {
void Jit::CompITypeMemUnpairedLRInner(MIPSOpcode op, X64Reg shiftReg)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
int o = op>>26;
MIPSGPReg rt = _RT;
@@ -285,7 +285,7 @@ namespace MIPSComp {
void Jit::Comp_ITypeMem(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU);
int offset = _IMM16;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@@ -334,7 +334,7 @@ namespace MIPSComp {
MIPSOpcode nextOp = GetOffsetInstruction(1);
// Looking for lwr rd, offset-3(rs) which makes a pair.
u32 desiredOp = ((op & 0xFFFF0000) + (4 << 26)) + (offset - 3);
if (!js.inDelaySlot && nextOp == desiredOp)
if (!js.inDelaySlot && nextOp == desiredOp && !jo.Disabled(JitDisable::LSU_UNALIGNED))
{
EatInstruction(nextOp);
// nextOp has the correct address.
@@ -350,7 +350,7 @@ namespace MIPSComp {
MIPSOpcode nextOp = GetOffsetInstruction(1);
// Looking for lwl rd, offset+3(rs) which makes a pair.
u32 desiredOp = ((op & 0xFFFF0000) - (4 << 26)) + (offset + 3);
if (!js.inDelaySlot && nextOp == desiredOp)
if (!js.inDelaySlot && nextOp == desiredOp && !jo.Disabled(JitDisable::LSU_UNALIGNED))
{
EatInstruction(nextOp);
// op has the correct address.
@@ -366,7 +366,7 @@ namespace MIPSComp {
MIPSOpcode nextOp = GetOffsetInstruction(1);
// Looking for swr rd, offset-3(rs) which makes a pair.
u32 desiredOp = ((op & 0xFFFF0000) + (4 << 26)) + (offset - 3);
if (!js.inDelaySlot && nextOp == desiredOp)
if (!js.inDelaySlot && nextOp == desiredOp && !jo.Disabled(JitDisable::LSU_UNALIGNED))
{
EatInstruction(nextOp);
// nextOp has the correct address.
@@ -382,7 +382,7 @@ namespace MIPSComp {
MIPSOpcode nextOp = GetOffsetInstruction(1);
// Looking for swl rd, offset+3(rs) which makes a pair.
u32 desiredOp = ((op & 0xFFFF0000) - (4 << 26)) + (offset + 3);
if (!js.inDelaySlot && nextOp == desiredOp)
if (!js.inDelaySlot && nextOp == desiredOp && !jo.Disabled(JitDisable::LSU_UNALIGNED))
{
EatInstruction(nextOp);
// op has the correct address.
+36 -36
View File
@@ -42,7 +42,7 @@
// Currently known non working ones should have DISABLE.
// #define CONDITIONAL_DISABLE { fpr.ReleaseSpillLocks(); Comp_Generic(op); return; }
#define CONDITIONAL_DISABLE ;
#define CONDITIONAL_DISABLE(flag) if (jo.Disabled(JitDisable::flag)) { Comp_Generic(op); return; }
#define DISABLE { fpr.ReleaseSpillLocks(); Comp_Generic(op); return; }
#define _RS MIPS_GET_RS(op)
@@ -74,7 +74,7 @@ alignas(16) const float identityMatrix[4][4] = { { 1.0f, 0, 0, 0 }, { 0, 1.0f, 0
void Jit::Comp_VPFX(MIPSOpcode op)
{
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int data = op & 0xFFFFF;
int regnum = (op >> 24) & 3;
switch (regnum) {
@@ -239,7 +239,7 @@ bool IsOverlapSafe(int dreg, int di, int sn, u8 sregs[], int tn = 0, u8 tregs[]
alignas(16) static u32 ssLoadStoreTemp;
void Jit::Comp_SV(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
s32 imm = (signed short)(op&0xFFFC);
int vt = ((op >> 16) & 0x1f) | ((op & 3) << 5);
@@ -294,7 +294,7 @@ void Jit::Comp_SV(MIPSOpcode op) {
}
void Jit::Comp_SVQ(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(LSU_VFPU);
int imm = (signed short)(op&0xFFFC);
int vt = (((op >> 16) & 0x1f)) | ((op&1) << 5);
@@ -502,7 +502,7 @@ void Jit::Comp_SVQ(MIPSOpcode op) {
}
void Jit::Comp_VVectorInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -557,7 +557,7 @@ void Jit::Comp_VVectorInit(MIPSOpcode op) {
}
void Jit::Comp_VIdt(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -608,7 +608,7 @@ void Jit::Comp_VIdt(MIPSOpcode op) {
}
void Jit::Comp_VDot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -739,7 +739,7 @@ void Jit::Comp_VDot(MIPSOpcode op) {
void Jit::Comp_VHdp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -788,7 +788,7 @@ void Jit::Comp_VHdp(MIPSOpcode op) {
}
void Jit::Comp_VCrossQuat(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -921,7 +921,7 @@ void Jit::Comp_VCrossQuat(MIPSOpcode op) {
}
void Jit::Comp_Vcmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix())
DISABLE;
@@ -997,7 +997,7 @@ static s32 DoVmaxSS(s32 treg) {
}
void Jit::Comp_VecDo3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1269,7 +1269,7 @@ alignas(16) static const u32 vcmpMask[4][4] = {
};
void Jit::Comp_Vcmp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_COMP);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1512,7 +1512,7 @@ extern const float mulTableVi2f[32] = {
};
void Jit::Comp_Vi2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1599,7 +1599,7 @@ void Jit::Comp_Vi2f(MIPSOpcode op) {
// Translation of ryg's half_to_float5_SSE2
void Jit::Comp_Vh2f(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1688,7 +1688,7 @@ alignas(16) static s8 vc2i_shuffle[16] = { -1, -1, -1, 0, -1, -1, -1, 1, -1, -
alignas(16) static s8 vuc2i_shuffle[16] = { 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3 };
void Jit::Comp_Vx2i(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1811,7 +1811,7 @@ static const float half = 0.5f;
static const double maxMinIntAsDouble[2] = { (double)0x7fffffff, (double)(int)0x80000000 }; // that's not equal to 0x80000000
void Jit::Comp_Vf2i(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1920,7 +1920,7 @@ void Jit::Comp_Vf2i(MIPSOpcode op) {
}
void Jit::Comp_Vcst(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -1957,7 +1957,7 @@ void Jit::Comp_Vcst(MIPSOpcode op) {
}
void Jit::Comp_Vsgn(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -2018,7 +2018,7 @@ void Jit::Comp_Vsgn(MIPSOpcode op) {
}
void Jit::Comp_Vocp(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -2067,7 +2067,7 @@ void Jit::Comp_Vocp(MIPSOpcode op) {
}
void Jit::Comp_Vbfy(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -2181,7 +2181,7 @@ void SinCosNegSin(SinCosArg angle, float *output) {
}
void Jit::Comp_VV2Op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -2419,7 +2419,7 @@ void Jit::Comp_VV2Op(MIPSOpcode op) {
}
void Jit::Comp_Mftv(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int imm = op & 0xFF;
MIPSGPReg rt = _RT;
@@ -2509,7 +2509,7 @@ void Jit::Comp_Mftv(MIPSOpcode op) {
}
void Jit::Comp_Vmfvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
@@ -2525,7 +2525,7 @@ void Jit::Comp_Vmfvc(MIPSOpcode op) {
}
void Jit::Comp_Vmtvc(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
int vs = _VS;
int imm = op & 0xFF;
if (imm >= 128 && imm < 128 + VFPU_CTRL_MAX) {
@@ -2549,7 +2549,7 @@ void Jit::Comp_Vmtvc(MIPSOpcode op) {
}
void Jit::Comp_VMatrixInit(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -2632,7 +2632,7 @@ void Jit::Comp_VMatrixInit(MIPSOpcode op) {
}
void Jit::Comp_Vmmov(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// TODO: This probably ignores prefixes?
if (js.HasUnknownPrefix())
@@ -2718,7 +2718,7 @@ void Jit::Comp_Vmmov(MIPSOpcode op) {
}
void Jit::Comp_VScl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -2780,7 +2780,7 @@ void Jit::Comp_VScl(MIPSOpcode op) {
}
void Jit::Comp_Vmmul(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// TODO: This probably ignores prefixes?
if (js.HasUnknownPrefix())
@@ -2974,7 +2974,7 @@ void Jit::Comp_Vmmul(MIPSOpcode op) {
}
void Jit::Comp_Vmscl(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// TODO: This op probably ignores prefixes?
if (js.HasUnknownPrefix())
@@ -3020,7 +3020,7 @@ void Jit::Comp_Vmscl(MIPSOpcode op) {
}
void Jit::Comp_Vtfm(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_MTX);
// TODO: This probably ignores prefixes? Or maybe uses D?
if (js.HasUnknownPrefix())
@@ -3163,7 +3163,7 @@ alignas(16) static const s8 vi2xc_shuffle[16] = { 3, 7, 11, 15, -1, -1, -1, -1,
alignas(16) static const s8 vi2xs_shuffle[16] = { 2, 3, 6, 7, 10, 11, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1 };
void Jit::Comp_Vi2x(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -3295,7 +3295,7 @@ void Jit::Comp_Vi2x(MIPSOpcode op) {
alignas(16) static const float vavg_table[4] = { 1.0f, 1.0f / 2.0f, 1.0f / 3.0f, 1.0f / 4.0f };
void Jit::Comp_Vhoriz(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
@@ -3412,7 +3412,7 @@ void Jit::Comp_Vhoriz(MIPSOpcode op) {
}
void Jit::Comp_Viim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -3435,7 +3435,7 @@ void Jit::Comp_Viim(MIPSOpcode op) {
}
void Jit::Comp_Vfim(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_XFER);
if (js.HasUnknownPrefix())
DISABLE;
@@ -3497,7 +3497,7 @@ void Jit::CompVrotShuffle(u8 *dregs, int imm, int n, bool negSin) {
// Very heavily used by FF:CC
void Jit::Comp_VRot(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix()) {
DISABLE;
}
@@ -3569,7 +3569,7 @@ void Jit::Comp_VRot(MIPSOpcode op) {
}
void Jit::Comp_ColorConv(MIPSOpcode op) {
CONDITIONAL_DISABLE;
CONDITIONAL_DISABLE(VFPU_VEC);
if (js.HasUnknownPrefix())
DISABLE;
+2 -2
View File
@@ -458,12 +458,12 @@ namespace Reporting
bool IsSupported()
{
// Disabled when using certain hacks, because they make for poor reports.
if (g_Config.bTimerHack)
return false;
if (CheatsInEffect())
return false;
if (g_Config.iLockedCPUSpeed != 0)
return false;
if (g_Config.uJitDisableFlags != 0)
return false;
// Don't allow builds without version info from git. They're useless for reporting.
if (strcmp(PPSSPP_GIT_VERSION, "unknown") == 0)
return false;
+8
View File
@@ -241,6 +241,7 @@ namespace SaveState
static bool needsProcess = false;
static std::vector<Operation> pending;
static std::mutex mutex;
static int screenshotFailures = 0;
static bool hasLoadedState = false;
static const int STALE_STATE_USES = 2;
// 4 hours of total gameplay since the virtual PSP started the game.
@@ -250,6 +251,7 @@ namespace SaveState
// TODO: Should this be configurable?
static const int REWIND_NUM_STATES = 20;
static const int SCREENSHOT_FAILURE_RETRIES = 15;
static StateRingbuffer rewindStates(REWIND_NUM_STATES);
// TODO: Any reason for this to be configurable?
const static float rewindMaxWallFrequency = 1.0f;
@@ -857,6 +859,12 @@ namespace SaveState
callbackResult = tempResult ? Status::SUCCESS : Status::FAILURE;
if (!tempResult) {
ERROR_LOG(SAVESTATE, "Failed to take a screenshot for the savestate! %s", op.filename.c_str());
if (screenshotFailures++ < SCREENSHOT_FAILURE_RETRIES) {
// Requeue for next frame.
SaveScreenshot(op.filename, op.callback, op.cbUserData);
}
} else {
screenshotFailures = 0;
}
break;
}
+2 -2
View File
@@ -51,7 +51,7 @@ void GenerateDepalShader300(char *buffer, GEBufferFormat pixelFormat, ShaderLang
WRITE(p, "precision mediump float;\n");
WRITE(p, "precision highp int;\n");
} else {
WRITE(p, "#version 330\n");
WRITE(p, "#version %d\n", gl_extensions.GLSLVersion());
}
WRITE(p, "in vec2 v_texcoord0;\n");
WRITE(p, "out vec4 fragColor0;\n");
@@ -252,7 +252,7 @@ void GenerateDepalShaderFloat(char *buffer, GEBufferFormat pixelFormat, ShaderLa
WRITE(p, "#version 100\n");
WRITE(p, "precision mediump float;\n");
} else {
WRITE(p, "#version 110\n");
WRITE(p, "#version %d\n", gl_extensions.GLSLVersion());
}
WRITE(p, "varying vec2 v_texcoord0;\n");
WRITE(p, "uniform sampler2D tex;\n");
+28 -8
View File
@@ -521,7 +521,7 @@ void DrawEngineCommon::DecodeVertsStep(u8 *dest, int &i, int &decodedVerts) {
decodedVerts += indexUpperBound - indexLowerBound + 1;
bool clockwise = true;
if (dc.cullMode != -1 && gstate.isCullEnabled() && gstate.getCullMode() != dc.cullMode) {
if (gstate.isCullEnabled() && gstate.getCullMode() != dc.cullMode) {
clockwise = false;
}
indexGen.AddPrim(dc.prim, dc.vertexCount, clockwise);
@@ -549,7 +549,7 @@ void DrawEngineCommon::DecodeVertsStep(u8 *dest, int &i, int &decodedVerts) {
case GE_VTYPE_IDX_8BIT >> GE_VTYPE_IDX_SHIFT:
for (int j = i; j <= lastMatch; j++) {
bool clockwise = true;
if (drawCalls[j].cullMode != -1 && gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) {
if (gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) {
clockwise = false;
}
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u8 *)drawCalls[j].inds, indexLowerBound, clockwise);
@@ -558,7 +558,7 @@ void DrawEngineCommon::DecodeVertsStep(u8 *dest, int &i, int &decodedVerts) {
case GE_VTYPE_IDX_16BIT >> GE_VTYPE_IDX_SHIFT:
for (int j = i; j <= lastMatch; j++) {
bool clockwise = true;
if (drawCalls[j].cullMode != -1 && gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) {
if (gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) {
clockwise = false;
}
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u16_le *)drawCalls[j].inds, indexLowerBound, clockwise);
@@ -567,7 +567,7 @@ void DrawEngineCommon::DecodeVertsStep(u8 *dest, int &i, int &decodedVerts) {
case GE_VTYPE_IDX_32BIT >> GE_VTYPE_IDX_SHIFT:
for (int j = i; j <= lastMatch; j++) {
bool clockwise = true;
if (drawCalls[j].cullMode != -1 && gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) {
if (gstate.isCullEnabled() && gstate.getCullMode() != drawCalls[j].cullMode) {
clockwise = false;
}
indexGen.TranslatePrim(drawCalls[j].prim, drawCalls[j].vertexCount, (const u32_le *)drawCalls[j].inds, indexLowerBound, clockwise);
@@ -731,10 +731,30 @@ void DrawEngineCommon::SubmitPrim(void *verts, void *inds, GEPrimitiveType prim,
}
if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) {
// Rendertarget == texture?
if (!g_Config.bDisableSlowFramebufEffects) {
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
DispatchFlush();
// Rendertarget == texture? Shouldn't happen. Still, try some mitigations.
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
DispatchFlush();
}
}
void TessellationDataTransfer::CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType) {
bool hasColor = (vertType & GE_VTYPE_COL_MASK) != 0;
bool hasTexCoord = (vertType & GE_VTYPE_TC_MASK) != 0;
for (int i = 0; i < size; ++i) {
memcpy(pos, points[i]->pos.AsArray(), 3 * sizeof(float));
pos += posStride;
}
if (hasTexCoord) {
for (int i = 0; i < size; ++i) {
memcpy(tex, points[i]->uv, 2 * sizeof(float));
tex += texStride;
}
}
if (hasColor) {
for (int i = 0; i < size; ++i) {
memcpy(col, Vec4f::FromRGBA(points[i]->color_32).AsArray(), 4 * sizeof(float));
col += colStride;
}
}
}
+5 -5
View File
@@ -54,6 +54,7 @@ namespace Spline { struct Weight2D; }
class TessellationDataTransfer {
public:
virtual ~TessellationDataTransfer() {}
void CopyControlPoints(float *pos, float *tex, float *col, int posStride, int texStride, int colStride, const SimpleVertex *const *points, int size, u32 vertType);
virtual void SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) = 0;
};
@@ -74,15 +75,15 @@ public:
// This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim
// is different. Should probably refactor that.
// Note that vertTypeID should be computed using GetVertTypeID().
virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int *bytesRead) {
SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, -1, bytesRead);
virtual void DispatchSubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead) {
SubmitPrim(verts, inds, prim, vertexCount, vertTypeID, cullMode, bytesRead);
}
bool TestBoundingBox(void* control_points, int vertexCount, u32 vertType, int *bytesRead);
void SubmitPrim(void *verts, void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead);
void SubmitSpline(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead);
void SubmitBezier(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead);
template<class Surface>
void SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope);
void ClearSplineBezierWeights();
std::vector<std::string> DebugGetVertexLoaderIDs();
@@ -130,7 +131,6 @@ protected:
// Vertex collector buffers
u8 *decoded = nullptr;
u16 *decIndex = nullptr;
u8 *splineBuffer = nullptr;
// Cached vertex decoders
u32 lastVType_ = -1;
+137 -129
View File
@@ -39,6 +39,7 @@
#include "GPU/Common/FramebufferCommon.h"
#include "GPU/Common/PostShader.h"
#include "GPU/Common/TextureCacheCommon.h"
#include "GPU/Debugger/Record.h"
#include "GPU/GPUInterface.h"
#include "GPU/GPUState.h"
@@ -147,14 +148,13 @@ void FramebufferManagerCommon::Init() {
bool FramebufferManagerCommon::UpdateSize() {
const bool newRender = renderWidth_ != (float)PSP_CoreParameter().renderWidth || renderHeight_ != (float)PSP_CoreParameter().renderHeight;
const bool newSettings = bloomHack_ != g_Config.iBloomHack || trueColor_ != g_Config.bTrueColor || useBufferedRendering_ != (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
const bool newSettings = bloomHack_ != g_Config.iBloomHack || useBufferedRendering_ != (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE);
renderWidth_ = (float)PSP_CoreParameter().renderWidth;
renderHeight_ = (float)PSP_CoreParameter().renderHeight;
pixelWidth_ = PSP_CoreParameter().pixelWidth;
pixelHeight_ = PSP_CoreParameter().pixelHeight;
bloomHack_ = g_Config.iBloomHack;
trueColor_ = g_Config.bTrueColor;
useBufferedRendering_ = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE;
return newRender || newSettings;
@@ -169,27 +169,24 @@ void FramebufferManagerCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, G
displayFramebufPtr_ = framebuf;
displayStride_ = stride;
displayFormat_ = format;
GPURecord::NotifyDisplay(framebuf, stride, format);
}
VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) {
addr &= 0x3FFFFFFF;
VirtualFramebuffer *match = nullptr;
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *v = vfbs_[i];
if (MaskedEqual(v->fb_address, addr)) {
if (v->fb_address == addr) {
// Could check w too but whatever
if (match == nullptr || match->last_frame_render < v->last_frame_render) {
match = v;
}
}
}
return match;
}
bool FramebufferManagerCommon::MaskedEqual(u32 addr1, u32 addr2) {
return (addr1 & 0x03FFFFFF) == (addr2 & 0x03FFFFFF);
}
u32 FramebufferManagerCommon::FramebufferByteSize(const VirtualFramebuffer *vfb) const {
return vfb->fb_stride * vfb->height * (vfb->format == GE_FORMAT_8888 ? 4 : 2);
}
@@ -255,11 +252,10 @@ void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, GEBufferForma
if (viewport_width != region_width) {
// The majority of the time, these are equal. If not, let's check what we know.
const u32 fb_normalized_address = fb_address | 0x44000000;
u32 nearest_address = 0xFFFFFFFF;
for (size_t i = 0; i < vfbs_.size(); ++i) {
const u32 other_address = vfbs_[i]->fb_address | 0x44000000;
if (other_address > fb_normalized_address && other_address < nearest_address) {
const u32 other_address = vfbs_[i]->fb_address & 0x3FFFFFFF;
if (other_address > fb_address && other_address < nearest_address) {
nearest_address = other_address;
}
}
@@ -268,7 +264,7 @@ void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, GEBufferForma
// This catches some cases where we can know this.
// Hmm. The problem is that we could only catch it for the first of two buffers...
const u32 bpp = fb_format == GE_FORMAT_8888 ? 4 : 2;
int avail_height = (nearest_address - fb_normalized_address) / (fb_stride * bpp);
int avail_height = (nearest_address - fb_address) / (fb_stride * bpp);
if (avail_height < drawing_height && avail_height == region_height) {
drawing_width = std::min(region_width, fb_stride);
drawing_height = avail_height;
@@ -284,11 +280,10 @@ void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, GEBufferForma
}
void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPUgstate &gstate) {
params->fb_addr = gstate.getFrameBufAddress();
params->fb_address = gstate.getFrameBufRawAddress();
params->fb_address = (gstate.getFrameBufRawAddress() & 0x3FFFFFFF) | 0x04000000; // GetFramebufferHeuristicInputs is only called from rendering, and thus, it's VRAM.
params->fb_stride = gstate.FrameBufStride();
params->z_address = gstate.getDepthBufRawAddress();
params->z_address = (gstate.getDepthBufRawAddress() & 0x3FFFFFFF) | 0x04000000;
params->z_stride = gstate.DepthBufStride();
params->fmt = gstate.FrameBufFormat();
@@ -350,6 +345,13 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
vfb->fb_stride = params.fb_stride;
vfb->format = params.fmt;
}
if (vfb->z_address == 0 && vfb->z_stride == 0) {
// Got one that was created by CreateRAMFramebuffer. Since it has no depth buffer,
// we just recreate it immediately.
ResizeFramebufFBO(vfb, vfb->width, vfb->height, true);
}
// Keep track, but this isn't really used.
vfb->z_stride = params.z_stride;
// Heuristic: In throughmode, a higher height could be used. Let's avoid shrinking the buffer.
@@ -420,8 +422,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
// None found? Create one.
if (!vfb) {
vfb = new VirtualFramebuffer();
memset(vfb, 0, sizeof(VirtualFramebuffer));
vfb = new VirtualFramebuffer{};
vfb->fbo = nullptr;
vfb->fb_address = params.fb_address;
vfb->fb_stride = params.fb_stride;
@@ -442,9 +443,9 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
SetColorUpdated(vfb, skipDrawReason);
u32 byteSize = FramebufferByteSize(vfb);
u32 fb_address_mem = (params.fb_address & 0x3FFFFFFF) | 0x04000000;
if (Memory::IsVRAMAddress(fb_address_mem) && fb_address_mem + byteSize > framebufRangeEnd_) {
framebufRangeEnd_ = fb_address_mem + byteSize;
// FB heuristics always produce an address in VRAM (this is during rendering) so we don't need to poke in the 0x04000000 flag here.
if (Memory::IsVRAMAddress(params.fb_address) && params.fb_address + byteSize > framebufRangeEnd_) {
framebufRangeEnd_ = params.fb_address + byteSize;
}
ResizeFramebufFBO(vfb, drawing_width, drawing_height, true);
@@ -458,8 +459,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
currentRenderVfb_ = vfb;
if (useBufferedRendering_ && !g_Config.bDisableSlowFramebufEffects) {
gpu->PerformMemoryUpload(fb_address_mem, byteSize);
NotifyStencilUpload(fb_address_mem, byteSize, true);
gpu->PerformMemoryUpload(params.fb_address, byteSize);
NotifyStencilUpload(params.fb_address, byteSize, true);
// TODO: Is it worth trying to upload the depth buffer?
}
@@ -589,7 +590,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe
shaderManager_->DirtyLastShader();
// Copy depth pixel value from the read framebuffer to the draw framebuffer
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
if (prevVfb) {
bool hasNewerDepth = prevVfb->last_frame_depth_render != 0 && prevVfb->last_frame_depth_render >= vfb->last_frame_depth_updated;
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !hasNewerDepth || isClearingDepth) {
// If depth wasn't updated, then we're at least "two degrees" away from the data.
@@ -682,7 +683,8 @@ void FramebufferManagerCommon::NotifyVideoUpload(u32 addr, int size, int width,
}
void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) {
addr &= ~0x40000000;
// Take off the uncached flag from the address. Not to be confused with the start of VRAM.
addr &= 0x3FFFFFFF;
// TODO: Could go through all FBOs, but probably not important?
// TODO: Could also check for inner changes, but video is most important.
bool isDisplayBuf = addr == DisplayFramebufAddr() || addr == PrevDisplayFramebufAddr();
@@ -693,7 +695,7 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) {
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
if (MaskedEqual(vfb->fb_address, addr)) {
if (vfb->fb_address == addr) {
FlushBeforeCopy();
if (useBufferedRendering_ && vfb->fbo) {
@@ -702,7 +704,7 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) {
// If we're not rendering to it, format may be wrong. Use displayFormat_ instead.
fmt = displayFormat_;
}
DrawPixels(vfb, 0, 0, Memory::GetPointer(addr | 0x04000000), fmt, vfb->fb_stride, vfb->width, vfb->height);
DrawPixels(vfb, 0, 0, Memory::GetPointer(addr), fmt, vfb->fb_stride, vfb->width, vfb->height);
SetColorUpdated(vfb, gstate_c.skipDrawReason);
} else {
INFO_LOG(FRAMEBUF, "Invalidating FBO for %08x (%i x %i x %i)", vfb->fb_address, vfb->width, vfb->height, vfb->format);
@@ -868,11 +870,13 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
VirtualFramebuffer *vfb = GetVFBAt(displayFramebufPtr_);
if (!vfb) {
// Let's search for a framebuf within this range.
const u32 addr = (displayFramebufPtr_ & 0x03FFFFFF) | 0x04000000;
// Let's search for a framebuf within this range. Note that we also look for
// "framebuffers" sitting in RAM so we only take off the kernel and uncached bits of the address
// when comparing.
const u32 addr = displayFramebufPtr_ & 0x3FFFFFFF;
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *v = vfbs_[i];
const u32 v_addr = (v->fb_address & 0x03FFFFFF) | 0x04000000;
const u32 v_addr = v->fb_address & 0x3FFFFFFF;
const u32 v_size = FramebufferByteSize(v);
if (addr >= v_addr && addr < v_addr + v_size) {
const u32 dstBpp = v->format == GE_FORMAT_8888 ? 4 : 2;
@@ -909,14 +913,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() {
if (!vfb) {
if (Memory::IsValidAddress(displayFramebufPtr_)) {
// The game is displaying something directly from RAM. In GTA, it's decoded video.
// First check that it's not a known RAM copy of a VRAM framebuffer though, as in MotoGP
for (auto iter = knownFramebufferRAMCopies_.begin(); iter != knownFramebufferRAMCopies_.end(); ++iter) {
if (iter->second == displayFramebufPtr_) {
vfb = GetVFBAt(iter->first);
}
}
if (!vfb) {
shaderManager_->DirtyLastShader();
if (useBufferedRendering_) {
@@ -1156,30 +1152,10 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
SetRenderSize(vfb);
bool trueColor = trueColor_;
if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) {
trueColor = true;
}
if (trueColor) {
vfb->colorDepth = Draw::FBO_8888;
} else {
switch (vfb->format) {
case GE_FORMAT_4444:
vfb->colorDepth = Draw::FBO_4444;
break;
case GE_FORMAT_5551:
vfb->colorDepth = Draw::FBO_5551;
break;
case GE_FORMAT_565:
vfb->colorDepth = Draw::FBO_565;
break;
case GE_FORMAT_8888:
default:
vfb->colorDepth = Draw::FBO_8888;
break;
}
}
// During hardware rendering, we always render at full color depth even if the game wouldn't on real hardware.
// It's not worth the trouble trying to support lower bit-depth rendering, just
// more cases to test that nobody will ever use.
vfb->colorDepth = Draw::FBO_8888;
textureCache_->ForgetLastTexture();
@@ -1203,7 +1179,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR, Draw::RPAction::CLEAR });
// GLES resets the blend state on clears.
gstate_c.Dirty(DIRTY_BLEND_STATE);
if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) {
if (!skipCopy) {
BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min((u16)oldWidth, std::min(vfb->bufferWidth, vfb->width)), std::min((u16)oldHeight, std::min(vfb->height, vfb->bufferHeight)), 0);
}
}
@@ -1223,6 +1199,8 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
}
}
// This is called from detected memcopies only. Not block transfers.
// MotoGP goes this path so we need to catch those copies here.
bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset, u32 skipDrawReason) {
if (size == 0) {
return false;
@@ -1243,7 +1221,8 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
continue;
}
const u32 vfb_address = (0x04000000 | vfb->fb_address) & 0x3FFFFFFF;
// We only remove the kernel and uncached bits when comparing.
const u32 vfb_address = vfb->fb_address & 0x3FFFFFFF;
const u32 vfb_size = FramebufferByteSize(vfb);
const u32 vfb_bpp = vfb->format == GE_FORMAT_8888 ? 4 : 2;
const u32 vfb_byteStride = vfb->fb_stride * vfb_bpp;
@@ -1282,15 +1261,6 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
}
}
if (srcBuffer && srcY == 0 && srcH == srcBuffer->height && !dstBuffer) {
// MotoGP workaround - it copies a framebuffer to memory and then displays it.
// TODO: It's rare anyway, but the game could modify the RAM and then we'd display the wrong thing.
// Unfortunately, that would force 1x render resolution.
if (Memory::IsRAMAddress(dst)) {
knownFramebufferRAMCopies_.insert(std::pair<u32, u32>(src, dst));
}
}
if (!useBufferedRendering_) {
// If we're copying into a recently used display buf, it's probably destined for the screen.
if (srcBuffer || (dstBuffer != displayFramebuf_ && dstBuffer != prevDisplayFramebuf_)) {
@@ -1298,17 +1268,23 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
}
}
if (!dstBuffer && srcBuffer && PSP_CoreParameter().compat.flags().BlockTransferAllowCreateFB) {
dstBuffer = CreateRAMFramebuffer(dst, srcBuffer->width, srcBuffer->height, srcBuffer->fb_stride, srcBuffer->format);
dstY = 0;
}
if (dstBuffer) {
dstBuffer->last_frame_used = gpuStats.numFlips;
}
if (dstBuffer && srcBuffer && !isMemset) {
if (srcBuffer == dstBuffer) {
WARN_LOG_REPORT_ONCE(dstsrccpy, G3D, "Intra-buffer memcpy (not supported) %08x -> %08x", src, dst);
} else {
WARN_LOG_REPORT_ONCE(dstnotsrccpy, G3D, "Inter-buffer memcpy %08x -> %08x", src, dst);
// Just do the blit!
if (g_Config.bBlockTransferGPU) {
BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0);
SetColorUpdated(dstBuffer, skipDrawReason);
RebindFramebuffer();
}
BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0);
SetColorUpdated(dstBuffer, skipDrawReason);
RebindFramebuffer();
}
return false;
} else if (dstBuffer) {
@@ -1316,15 +1292,12 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
gpuStats.numClears++;
}
WARN_LOG_ONCE(btucpy, G3D, "Memcpy fbo upload %08x -> %08x", src, dst);
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
const u8 *srcBase = Memory::GetPointerUnchecked(src);
DrawPixels(dstBuffer, 0, dstY, srcBase, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstH);
SetColorUpdated(dstBuffer, skipDrawReason);
RebindFramebuffer();
// This is a memcpy, let's still copy just in case.
return false;
}
FlushBeforeCopy();
const u8 *srcBase = Memory::GetPointerUnchecked(src);
DrawPixels(dstBuffer, 0, dstY, srcBase, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstH);
SetColorUpdated(dstBuffer, skipDrawReason);
RebindFramebuffer();
// This is a memcpy, let's still copy just in case.
return false;
} else if (srcBuffer) {
WARN_LOG_ONCE(btdcpy, G3D, "Memcpy fbo download %08x -> %08x", src, dst);
@@ -1341,7 +1314,8 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
}
}
void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) const {
// Can't be const, in case it has to create a vfb unfortunately.
void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) {
u32 dstYOffset = -1;
u32 dstXOffset = -1;
u32 srcYOffset = -1;
@@ -1354,7 +1328,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
const u32 vfb_address = (0x04000000 | vfb->fb_address) & 0x3FFFFFFF;
const u32 vfb_address = vfb->fb_address & 0x3FFFFFFF;
const u32 vfb_size = FramebufferByteSize(vfb);
const u32 vfb_bpp = vfb->format == GE_FORMAT_8888 ? 4 : 2;
const u32 vfb_byteStride = vfb->fb_stride * vfb_bpp;
@@ -1421,6 +1395,16 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst
}
}
if (!dstBuffer && PSP_CoreParameter().compat.flags().BlockTransferAllowCreateFB) {
GEBufferFormat ramFormat = bpp == 4 ? GE_FORMAT_8888 : GE_FORMAT_5551;
// TODO: We don't really know the 16-bit format here.. at all. Can only guess when it gets used later!
// But actually, the format of the source buffer is probably not a bad guess..
dstBuffer = CreateRAMFramebuffer(dstBasePtr, dstWidth, dstHeight, dstStride, ramFormat);
}
if (dstBuffer)
dstBuffer->last_frame_used = gpuStats.numFlips;
if (dstYOffset != (u32)-1) {
dstY += dstYOffset;
dstX += dstXOffset;
@@ -1431,6 +1415,38 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst
}
}
VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAddress, int width, int height, int stride, GEBufferFormat format) {
float renderWidthFactor = renderWidth_ / 480.0f;
float renderHeightFactor = renderHeight_ / 272.0f;
// A target for the destination is missing - so just create one!
// Make sure this one would be found by the algorithm above so we wouldn't
// create a new one each frame.
VirtualFramebuffer *vfb = new VirtualFramebuffer{};
vfb->fbo = nullptr;
vfb->fb_address = fbAddress; // NOTE - not necessarily in VRAM!
vfb->fb_stride = stride;
vfb->z_address = 0; // marks that if anyone tries to render to this framebuffer, it should be dropped and recreated.
vfb->z_stride = 0;
vfb->width = std::max(width, stride);
vfb->height = height;
vfb->newWidth = vfb->width;
vfb->newHeight = vfb->height;
vfb->lastFrameNewSize = gpuStats.numFlips;
vfb->renderWidth = (u16)(vfb->width * renderWidthFactor);
vfb->renderHeight = (u16)(vfb->height * renderHeightFactor);
vfb->bufferWidth = vfb->width;
vfb->bufferHeight = vfb->height;
vfb->format = format;
vfb->drawnFormat = GE_FORMAT_8888;
vfb->usageFlags = FB_USAGE_RENDERTARGET;
SetColorUpdated(vfb, 0);
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED);
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth });
vfbs_.push_back(vfb);
return vfb;
}
// 1:1 pixel sides buffers, we resize buffers to these before we read them back.
VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFramebuffer *vfb) {
// For now we'll keep these on the same struct as the ones that can get displayed
@@ -1619,29 +1635,23 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst
if (srcBuffer == dstBuffer) {
if (srcX != dstX || srcY != dstY) {
WARN_LOG_ONCE(dstsrc, G3D, "Intra-buffer block transfer %08x -> %08x", srcBasePtr, dstBasePtr);
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
BlitFramebuffer(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp);
RebindFramebuffer();
SetColorUpdated(dstBuffer, skipDrawReason);
return true;
}
} else {
// Ignore, nothing to do. Tales of Phantasia X does this by accident.
if (g_Config.bBlockTransferGPU) {
return true;
}
}
} else {
WARN_LOG_ONCE(dstnotsrc, G3D, "Inter-buffer block transfer %08x -> %08x", srcBasePtr, dstBasePtr);
// Just do the blit!
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
BlitFramebuffer(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp);
RebindFramebuffer();
SetColorUpdated(dstBuffer, skipDrawReason);
return true; // No need to actually do the memory copy behind, probably.
return true;
} else {
// Ignore, nothing to do. Tales of Phantasia X does this by accident.
return true;
}
} else {
WARN_LOG_ONCE(dstnotsrc, G3D, "Inter-buffer block transfer %08x -> %08x", srcBasePtr, dstBasePtr);
// Just do the blit!
FlushBeforeCopy();
BlitFramebuffer(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp);
RebindFramebuffer();
SetColorUpdated(dstBuffer, skipDrawReason);
return true; // No need to actually do the memory copy behind, probably.
}
return false;
} else if (dstBuffer) {
@@ -1699,26 +1709,24 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS
if (dstBuffer && !srcBuffer) {
WARN_LOG_ONCE(btu, G3D, "Block transfer upload %08x -> %08x", srcBasePtr, dstBasePtr);
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
const u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp;
int dstBpp = dstBuffer->format == GE_FORMAT_8888 ? 4 : 2;
float dstXFactor = (float)bpp / dstBpp;
if (dstWidth > dstBuffer->width || dstHeight > dstBuffer->height) {
// The buffer isn't big enough, and we have a clear hint of size. Resize.
// This happens in Valkyrie Profile when uploading video at the ending.
ResizeFramebufFBO(dstBuffer, dstWidth, dstHeight, false, true);
// Make sure we don't flop back and forth.
dstBuffer->newWidth = std::max(dstWidth, (int)dstBuffer->width);
dstBuffer->newHeight = std::max(dstHeight, (int)dstBuffer->height);
dstBuffer->lastFrameNewSize = gpuStats.numFlips;
// Resizing may change the viewport/etc.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE);
}
DrawPixels(dstBuffer, static_cast<int>(dstX * dstXFactor), dstY, srcBase, dstBuffer->format, static_cast<int>(srcStride * dstXFactor), static_cast<int>(dstWidth * dstXFactor), dstHeight);
SetColorUpdated(dstBuffer, skipDrawReason);
RebindFramebuffer();
FlushBeforeCopy();
const u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp;
int dstBpp = dstBuffer->format == GE_FORMAT_8888 ? 4 : 2;
float dstXFactor = (float)bpp / dstBpp;
if (dstWidth > dstBuffer->width || dstHeight > dstBuffer->height) {
// The buffer isn't big enough, and we have a clear hint of size. Resize.
// This happens in Valkyrie Profile when uploading video at the ending.
ResizeFramebufFBO(dstBuffer, dstWidth, dstHeight, false, true);
// Make sure we don't flop back and forth.
dstBuffer->newWidth = std::max(dstWidth, (int)dstBuffer->width);
dstBuffer->newHeight = std::max(dstHeight, (int)dstBuffer->height);
dstBuffer->lastFrameNewSize = gpuStats.numFlips;
// Resizing may change the viewport/etc.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE);
}
DrawPixels(dstBuffer, static_cast<int>(dstX * dstXFactor), dstY, srcBase, dstBuffer->format, static_cast<int>(srcStride * dstXFactor), static_cast<int>(dstWidth * dstXFactor), dstHeight);
SetColorUpdated(dstBuffer, skipDrawReason);
RebindFramebuffer();
}
}
}
@@ -1917,7 +1925,7 @@ bool FramebufferManagerCommon::GetFramebuffer(u32 fb_address, int fb_stride, GEB
if (!vfb) {
// If there's no vfb and we're drawing there, must be memory?
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address | 0x04000000), fb_stride, 512, format);
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, format);
return true;
}
@@ -1971,7 +1979,7 @@ bool FramebufferManagerCommon::GetDepthbuffer(u32 fb_address, int fb_stride, u32
if (!vfb) {
// If there's no vfb and we're drawing there, must be memory?
buffer = GPUDebugBuffer(Memory::GetPointer(z_address | 0x04000000), z_stride, 512, GPU_DBG_FORMAT_16BIT);
buffer = GPUDebugBuffer(Memory::GetPointer(z_address), z_stride, 512, GPU_DBG_FORMAT_16BIT);
return true;
}
@@ -2007,7 +2015,7 @@ bool FramebufferManagerCommon::GetStencilbuffer(u32 fb_address, int fb_stride, G
if (!vfb) {
// If there's no vfb and we're drawing there, must be memory?
// TODO: Actually get the stencil.
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address | 0x04000000), fb_stride, 512, GPU_DBG_FORMAT_8888);
buffer = GPUDebugBuffer(Memory::GetPointer(fb_address), fb_stride, 512, GPU_DBG_FORMAT_8888);
return true;
}
@@ -2059,7 +2067,7 @@ void FramebufferManagerCommon::PackFramebufferSync_(VirtualFramebuffer *vfb, int
return;
}
const u32 fb_address = (0x04000000) | vfb->fb_address;
const u32 fb_address = vfb->fb_address & 0x3FFFFFFF;
Draw::DataFormat destFormat = GEFormatToThin3D(vfb->format);
const int dstBpp = (int)DataFormatSizeInBytes(destFormat);
+7 -7
View File
@@ -119,7 +119,6 @@ struct VirtualFramebuffer {
};
struct FramebufferHeuristicParams {
u32 fb_addr;
u32 fb_address;
int fb_stride;
u32 z_address;
@@ -147,6 +146,8 @@ enum BindFramebufferColorFlags {
BINDFBCOLOR_MAY_COPY = 1,
BINDFBCOLOR_MAY_COPY_WITH_UV = 3,
BINDFBCOLOR_APPLY_TEX_OFFSET = 4,
// Used when rendering to a temporary surface (e.g. not the current render target.)
BINDFBCOLOR_FORCE_SELF = 8,
};
enum DrawTextureFlags {
@@ -243,10 +244,10 @@ public:
size_t NumVFBs() const { return vfbs_.size(); }
u32 PrevDisplayFramebufAddr() {
return prevDisplayFramebuf_ ? (0x04000000 | prevDisplayFramebuf_->fb_address) : 0;
return prevDisplayFramebuf_ ? prevDisplayFramebuf_->fb_address : 0;
}
u32 DisplayFramebufAddr() {
return displayFramebuf_ ? (0x04000000 | displayFramebuf_->fb_address) : 0;
return displayFramebuf_ ? displayFramebuf_->fb_address : 0;
}
u32 DisplayFramebufStride() {
@@ -332,7 +333,6 @@ protected:
void EstimateDrawingSize(u32 fb_address, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int fb_stride, int &drawing_width, int &drawing_height);
u32 FramebufferByteSize(const VirtualFramebuffer *vfb) const;
static bool MaskedEqual(u32 addr1, u32 addr2);
void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb);
void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged);
@@ -346,10 +346,12 @@ protected:
bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const;
void DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb);
void FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) const;
void FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp);
VirtualFramebuffer *FindDownloadTempBuffer(VirtualFramebuffer *vfb);
virtual bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) = 0;
virtual void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) = 0;
VirtualFramebuffer *CreateRAMFramebuffer(uint32_t fbAddress, int width, int height, int stride, GEBufferFormat format);
void OptimizeDownloadRange(VirtualFramebuffer *vfb, int &x, int &y, int &w, int &h);
void UpdateFramebufUsage(VirtualFramebuffer *vfb);
@@ -393,7 +395,6 @@ protected:
std::vector<VirtualFramebuffer *> vfbs_;
std::vector<VirtualFramebuffer *> bvfbs_; // blitting framebuffers (for download)
std::set<std::pair<u32, u32>> knownFramebufferRAMCopies_;
bool gameUsesSequentialCopies_ = false;
@@ -403,7 +404,6 @@ protected:
int pixelWidth_;
int pixelHeight_;
int bloomHack_ = 0;
bool trueColor_ = false;
// Used by post-processing shaders
std::vector<Draw::Framebuffer *> extraFBOs_;
+22 -15
View File
@@ -40,6 +40,17 @@ bool CanUseHardwareTransform(int prim) {
return !gstate.isModeThrough() && prim != GE_PRIM_RECTANGLES;
}
bool IsStencilTestOutputDisabled() {
// The mask applies on all stencil ops.
if (gstate.isStencilTestEnabled() && (gstate.pmska & 0xFF) != 0xFF) {
if (gstate.FrameBufFormat() == GE_FORMAT_565) {
return true;
}
return gstate.getStencilOpZPass() == GE_STENCILOP_KEEP && gstate.getStencilOpZFail() == GE_STENCILOP_KEEP && gstate.getStencilOpSFail() == GE_STENCILOP_KEEP;
}
return true;
}
bool NeedsTestDiscard() {
// We assume this is called only when enabled and not trivially true (may also be for color testing.)
if (gstate.isStencilTestEnabled() && (gstate.pmska & 0xFF) != 0xFF)
@@ -170,7 +181,7 @@ const bool nonAlphaDestFactors[16] = {
};
ReplaceAlphaType ReplaceAlphaWithStencil(ReplaceBlendType replaceBlend) {
if (!gstate.isStencilTestEnabled() || gstate.isModeClear()) {
if (IsStencilTestOutputDisabled() || gstate.isModeClear()) {
return REPLACE_ALPHA_NO;
}
@@ -510,7 +521,7 @@ float DepthSliceFactor() {
}
// This is used for float values which might not be integers, but are in the integer scale of 65535.
static float ToScaledDepthFromInteger(float z) {
float ToScaledDepthFromIntegerScale(float z) {
if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) {
return z * (1.0f / 65535.0f);
}
@@ -526,10 +537,6 @@ static float ToScaledDepthFromInteger(float z) {
}
}
float ToScaledDepth(u16 z) {
return ToScaledDepthFromInteger((float)(int)z);
}
float FromScaledDepth(float z) {
if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) {
return z * 65535.0f;
@@ -595,8 +602,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
out.viewportY = renderY + displayOffsetY;
out.viewportW = curRTWidth * renderWidthFactor;
out.viewportH = curRTHeight * renderHeightFactor;
out.depthRangeMin = ToScaledDepthFromInteger(0);
out.depthRangeMax = ToScaledDepthFromInteger(65536);
out.depthRangeMin = ToScaledDepthFromIntegerScale(0);
out.depthRangeMax = ToScaledDepthFromIntegerScale(65536);
} else {
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
float vpXScale = gstate.getViewportXScale();
@@ -705,11 +712,11 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) {
zScale = 1.0f;
zOffset = 0.0f;
out.depthRangeMin = ToScaledDepthFromInteger(vpZCenter - vpZScale);
out.depthRangeMax = ToScaledDepthFromInteger(vpZCenter + vpZScale);
out.depthRangeMin = ToScaledDepthFromIntegerScale(vpZCenter - vpZScale);
out.depthRangeMax = ToScaledDepthFromIntegerScale(vpZCenter + vpZScale);
} else {
out.depthRangeMin = ToScaledDepthFromInteger(minz);
out.depthRangeMax = ToScaledDepthFromInteger(maxz);
out.depthRangeMin = ToScaledDepthFromIntegerScale(minz);
out.depthRangeMax = ToScaledDepthFromIntegerScale(maxz);
}
// OpenGL will clamp these for us anyway, and Direct3D will error if not clamped.
@@ -996,7 +1003,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
int constantAlpha = 255;
BlendFactor constantAlphaGL = BlendFactor::ONE;
if (gstate.isStencilTestEnabled() && replaceAlphaWithStencil == REPLACE_ALPHA_NO) {
if (!IsStencilTestOutputDisabled() && replaceAlphaWithStencil == REPLACE_ALPHA_NO) {
switch (ReplaceAlphaWithStencilType()) {
case STENCIL_VALUE_UNIFORM:
constantAlpha = gstate.getStencilTestRef();
@@ -1164,7 +1171,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) {
blendState.setFactors(glBlendFuncA, glBlendFuncB, BlendFactor::ONE, BlendFactor::ZERO);
break;
}
} else if (gstate.isStencilTestEnabled()) {
} else if (!IsStencilTestOutputDisabled()) {
switch (ReplaceAlphaWithStencilType()) {
case STENCIL_VALUE_KEEP:
blendState.setFactors(glBlendFuncA, glBlendFuncB, BlendFactor::ZERO, BlendFactor::ONE);
@@ -1332,7 +1339,7 @@ static void ConvertStencilFunc5551(GenericStencilFuncState &state) {
}
void ConvertStencilFuncState(GenericStencilFuncState &state) {
state.enabled = gstate.isStencilTestEnabled() && !g_Config.bDisableStencilTest;
state.enabled = gstate.isStencilTestEnabled();
if (!state.enabled)
return;
+2 -1
View File
@@ -45,6 +45,7 @@ bool IsColorTestAgainstZero();
bool IsColorTestTriviallyTrue();
bool IsAlphaTestAgainstZero();
bool NeedsTestDiscard();
bool IsStencilTestOutputDisabled();
StencilValueType ReplaceAlphaWithStencilType();
ReplaceAlphaType ReplaceAlphaWithStencil(ReplaceBlendType replaceBlend);
@@ -71,7 +72,7 @@ struct ViewportAndScissor {
bool dirtyDepth;
};
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out);
float ToScaledDepth(u16 z);
float ToScaledDepthFromIntegerScale(float z);
float FromScaledDepth(float z);
float DepthSliceFactor();
+10 -2
View File
@@ -77,6 +77,10 @@ void IndexGenerator::AddList(int numVerts, bool clockwise) {
count_ += numVerts;
prim_ = GE_PRIM_TRIANGLES;
seenPrims_ |= 1 << GE_PRIM_TRIANGLES;
if (!clockwise) {
// Make sure we don't treat this as pure.
seenPrims_ |= 1 << GE_PRIM_TRIANGLE_STRIP;
}
}
void IndexGenerator::AddStrip(int numVerts, bool clockwise) {
@@ -96,7 +100,7 @@ void IndexGenerator::AddStrip(int numVerts, bool clockwise) {
if (numTris > 0)
count_ += numTris * 3;
// This is so we can detect one single strip by just looking at seenPrims_.
if (!seenPrims_) {
if (!seenPrims_ && clockwise) {
seenPrims_ = 1 << GE_PRIM_TRIANGLE_STRIP;
prim_ = GE_PRIM_TRIANGLE_STRIP;
pureCount_ = numVerts;
@@ -123,6 +127,10 @@ void IndexGenerator::AddFan(int numVerts, bool clockwise) {
count_ += numTris * 3;
prim_ = GE_PRIM_TRIANGLES;
seenPrims_ |= 1 << GE_PRIM_TRIANGLE_FAN;
if (!clockwise) {
// Make sure we don't treat this as pure.
seenPrims_ |= 1 << GE_PRIM_TRIANGLE_STRIP;
}
}
//Lines
@@ -218,7 +226,7 @@ void IndexGenerator::TranslateList(int numInds, const ITypeLE *inds, int indexOf
indexOffset = index_ - indexOffset;
// We only bother doing this minor optimization in triangle list, since it's by far the most
// common operation that can benefit.
if (sizeof(ITypeLE) == sizeof(inds_[0]) && indexOffset == 0) {
if (sizeof(ITypeLE) == sizeof(inds_[0]) && indexOffset == 0 && clockwise) {
memcpy(inds_, inds, numInds * sizeof(ITypeLE));
inds_ += numInds;
count_ += numInds;
+8 -1
View File
@@ -19,6 +19,10 @@
#include <cstdint>
namespace Draw {
class DrawContext;
}
enum ShaderLanguage {
GLSL_140,
GLSL_300,
@@ -117,10 +121,13 @@ enum : uint64_t {
class ShaderManagerCommon {
public:
ShaderManagerCommon() {}
ShaderManagerCommon(Draw::DrawContext *draw) : draw_(draw) {}
virtual ~ShaderManagerCommon() {}
virtual void DirtyLastShader() = 0;
protected:
Draw::DrawContext *draw_ = nullptr;
};
struct TBuiltInResource;
+19 -12
View File
@@ -1,6 +1,7 @@
#include <string>
#include <sstream>
#include "thin3d/thin3d.h"
#include "Common/StringUtils.h"
#include "Core/Config.h"
@@ -60,7 +61,7 @@ std::string VertexShaderDesc(const ShaderID &id) {
}
void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform) {
bool isModeThrough = gstate.isModeThrough();
bool isModeThrough = (vertType & GE_VTYPE_THROUGH) != 0;
bool doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
bool doTextureTransform = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
bool doShadeMapping = doTexture && (gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP);
@@ -72,6 +73,7 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
bool doBezier = gstate_c.bezier;
bool doSpline = gstate_c.spline;
// These are the original vertType's values (normalized will always have colors, etc.)
bool hasColorTess = (gstate.vertType & GE_VTYPE_COL_MASK) != 0 && (doBezier || doSpline);
bool hasTexcoordTess = (gstate.vertType & GE_VTYPE_TC_MASK) != 0 && (doBezier || doSpline);
bool hasNormalTess = (gstate.vertType & GE_VTYPE_NRM_MASK) != 0 && (doBezier || doSpline);
@@ -115,18 +117,15 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform)
id.SetBits(VS_BIT_WEIGHT_FMTSCALE, 2, (vertType & GE_VTYPE_WEIGHT_MASK) >> GE_VTYPE_WEIGHT_SHIFT);
}
// Okay, d[1] coming up. ==============
if (gstate.isLightingEnabled() || doShadeMapping) {
// doShadeMapping is stored as UVGenMode, so this is enough for isLightingEnabled.
if (gstate.isLightingEnabled()) {
id.SetBits(VS_BIT_MATERIAL_UPDATE, 3, gstate.getMaterialUpdate() & 7);
id.SetBit(VS_BIT_LIGHTING_ENABLE);
}
if (gstate.isLightingEnabled()) {
// doShadeMapping is stored as UVGenMode, and light type doesn't matter for shade mapping.
id.SetBits(VS_BIT_MATERIAL_UPDATE, 3, gstate.getMaterialUpdate() & 7);
id.SetBit(VS_BIT_LIGHTING_ENABLE);
// Light bits
for (int i = 0; i < 4; i++) {
bool chanEnabled = gstate.isLightChanEnabled(i) != 0 && gstate.isLightingEnabled();
bool chanEnabled = gstate.isLightChanEnabled(i) != 0;
id.SetBit(VS_BIT_LIGHT0_ENABLE + i, chanEnabled);
if (chanEnabled || (doShadeMapping && (gstate.getUVLS0() == i || gstate.getUVLS1() == i))) {
if (chanEnabled) {
id.SetBits(VS_BIT_LIGHT0_COMP + 4 * i, 2, gstate.getLightComputation(i));
id.SetBits(VS_BIT_LIGHT0_TYPE + 4 * i, 2, gstate.getLightType(i));
}
@@ -201,8 +200,10 @@ std::string FragmentShaderDesc(const ShaderID &id) {
case STENCIL_VALUE_INCR_8: desc << "StenIncr8 "; break;
case STENCIL_VALUE_DECR_4: desc << "StenDecr4 "; break;
case STENCIL_VALUE_DECR_8: desc << "StenDecr4 "; break;
default: desc << "StenUnknown"; break;
default: desc << "StenUnknown "; break;
}
} else if (id.Bit(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE)) {
desc << "StenOff ";
}
if (id.Bit(FS_BIT_DO_TEXTURE)) {
switch (id.Bits(FS_BIT_TEXFUNC, 3)) {
@@ -225,7 +226,7 @@ std::string FragmentShaderDesc(const ShaderID &id) {
// Here we must take all the bits of the gstate that determine what the fragment shader will
// look like, and concatenate them together into an ID.
void ComputeFragmentShaderID(ShaderID *id_out) {
void ComputeFragmentShaderID(ShaderID *id_out, const Draw::Bugs &bugs) {
ShaderID id;
if (gstate.isModeClear()) {
// We only need one clear shader, so let's ignore the rest of the bits.
@@ -309,6 +310,12 @@ void ComputeFragmentShaderID(ShaderID *id_out) {
id.SetBit(FS_BIT_FLATSHADE, doFlatShading);
id.SetBit(FS_BIT_SHADER_DEPAL, useShaderDepal);
if (g_Config.bVendorBugChecksEnabled) {
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL)) {
id.SetBit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL, !IsStencilTestOutputDisabled() && !gstate.isDepthWriteEnabled());
}
}
}
*id_out = id;
+7 -3
View File
@@ -87,7 +87,8 @@ enum {
FS_BIT_FLATSHADE = 46,
FS_BIT_BGRA_TEXTURE = 47,
FS_BIT_TEST_DISCARD_TO_ZERO = 48,
// 49+ are free.
FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL = 49,
// 50+ are free.
};
struct ShaderID {
@@ -175,12 +176,15 @@ struct FShaderID : ShaderID {
}
};
namespace Draw {
class Bugs;
}
bool CanUseHardwareTransform(int prim);
void ComputeVertexShaderID(ShaderID *id, uint32_t vertexType, bool useHWTransform);
// Generates a compact string that describes the shader. Useful in a list to get an overview
// of the current flora of shaders.
std::string VertexShaderDesc(const ShaderID &id);
void ComputeFragmentShaderID(ShaderID *id);
void ComputeFragmentShaderID(ShaderID *id, const Draw::Bugs &bugs);
std::string FragmentShaderDesc(const ShaderID &id);
+21 -3
View File
@@ -42,9 +42,27 @@ void CalcCullRange(float minValues[4], float maxValues[4], bool flipViewport, bo
return (pspViewport - gstate_c.vpYOffset) * heightScale;
};
auto reverseViewportZ = [hasNegZ](float z) {
float pspViewport = (z - gstate.getViewportZCenter()) * (1.0f / gstate.getViewportZScale());
// Differs from GLES: depth is 0 to 1, not -1 to 1.
float realViewport = (pspViewport - gstate_c.vpZOffset) * gstate_c.vpDepthScale;
float vpZScale = gstate.getViewportZScale();
float vpZCenter = gstate.getViewportZCenter();
float scale, center;
if (gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) {
// These are just the reverse of the formulas in GPUStateUtils.
float halfActualZRange = vpZScale * (1.0f / gstate_c.vpDepthScale);
float minz = -((gstate_c.vpZOffset * halfActualZRange) - vpZCenter) - halfActualZRange;
// In accurate depth mode, we're comparing against a value scaled to (minz, maxz).
// And minz might be very negative, (e.g. if we're clamping in that direction.)
scale = halfActualZRange;
center = minz + halfActualZRange;
} else {
// In old-style depth mode, we're comparing against a value scaled to viewport.
// (and possibly incorrectly clipped against it.)
scale = vpZScale;
center = vpZCenter;
}
float realViewport = (z - center) * (1.0f / scale);
return hasNegZ ? realViewport : (realViewport * 0.5f + 0.5f);
};
auto sortPair = [](float a, float b) {
+42 -28
View File
@@ -191,9 +191,9 @@ void SoftwareTransform(
fog_slope = std::signbit(fog_slope) ? -65535.0f : 65535.0f;
}
int colorIndOffset = 0;
int provokeIndOffset = 0;
if (params->provokeFlatFirst) {
colorIndOffset = ColorIndexOffset(prim, gstate.getShadeMode(), gstate.isModeClear());
provokeIndOffset = ColorIndexOffset(prim, gstate.getShadeMode(), gstate.isModeClear());
}
VertexReader reader(decoded, decVtxFormat, vertType);
@@ -206,8 +206,8 @@ void SoftwareTransform(
reader.ReadPos(vert.pos);
if (reader.hasColor0()) {
if (colorIndOffset != 0 && index + colorIndOffset < maxIndex) {
reader.Goto(index + colorIndOffset);
if (provokeIndOffset != 0 && index + provokeIndOffset < maxIndex) {
reader.Goto(index + provokeIndOffset);
reader.ReadColor0_8888(vert.color0);
reader.Goto(index);
} else {
@@ -247,10 +247,24 @@ void SoftwareTransform(
Vec3f worldnormal(0, 0, 1);
reader.ReadPos(pos);
float ruv[2] = { 0.0f, 0.0f };
if (reader.hasUV())
reader.ReadUV(ruv);
// Read all the provoking vertex values here.
Vec4f unlitColor;
if (provokeIndOffset != 0 && index + provokeIndOffset < maxIndex)
reader.Goto(index + provokeIndOffset);
if (reader.hasColor0())
reader.ReadColor0(unlitColor.AsArray());
else
unlitColor = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA());
if (reader.hasNormal())
reader.ReadNrm(normal.AsArray());
if (!skinningEnabled) {
Vec3ByMatrix43(out, pos, gstate.worldMatrix);
if (reader.hasNormal()) {
reader.ReadNrm(normal.AsArray());
if (gstate.areNormalsReversed()) {
normal = -normal;
}
@@ -259,9 +273,9 @@ void SoftwareTransform(
}
} else {
float weights[8];
// TODO: For flat, are weights from the provoking used for color/normal?
reader.Goto(index);
reader.ReadWeights(weights);
if (reader.hasNormal())
reader.ReadNrm(normal.AsArray());
// Skinning
Vec3f psum(0, 0, 0);
@@ -291,20 +305,7 @@ void SoftwareTransform(
}
}
// Perform lighting here if enabled. don't need to check through, it's checked above.
Vec4f unlitColor = Vec4f(1, 1, 1, 1);
if (reader.hasColor0()) {
if (colorIndOffset != 0 && index + colorIndOffset < maxIndex) {
reader.Goto(index + colorIndOffset);
reader.ReadColor0(&unlitColor.x);
reader.Goto(index);
} else {
reader.ReadColor0(&unlitColor.x);
}
} else {
unlitColor = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA());
}
// Perform lighting here if enabled.
if (gstate.isLightingEnabled()) {
float litColor0[4];
float litColor1[4];
@@ -338,10 +339,6 @@ void SoftwareTransform(
}
}
float ruv[2] = {0.0f, 0.0f};
if (reader.hasUV())
reader.ReadUV(ruv);
// Perform texture coordinate generation after the transform and lighting - one style of UV depends on lights.
switch (gstate.getUVGenMode()) {
case GE_TEXMAP_TEXTURE_COORDS: // UV mapping
@@ -354,6 +351,8 @@ void SoftwareTransform(
case GE_TEXMAP_TEXTURE_MATRIX:
{
// TODO: What's the correct behavior with flat shading? Provoked normal or real normal?
// Projection mapping
Vec3f source;
switch (gstate.getUVProjMode()) {
@@ -391,8 +390,23 @@ void SoftwareTransform(
case GE_TEXMAP_ENVIRONMENT_MAP:
// Shade mapping - use two light sources to generate U and V.
{
Vec3f lightpos0 = Vec3f(&lighter.lpos[gstate.getUVLS0() * 3]).Normalized();
Vec3f lightpos1 = Vec3f(&lighter.lpos[gstate.getUVLS1() * 3]).Normalized();
auto getLPosFloat = [&](int l, int i) {
return getFloat24(gstate.lpos[l * 3 + i]);
};
auto getLPos = [&](int l) {
return Vec3f(getLPosFloat(l, 0), getLPosFloat(l, 1), getLPosFloat(l, 2));
};
auto calcShadingLPos = [&](int l) {
Vec3f pos = getLPos(l);
if (pos.Length2() == 0.0f) {
return Vec3f(0.0f, 0.0f, 1.0f);
} else {
return pos.Normalized();
}
};
// Might not have lighting enabled, so don't use lighter.
Vec3f lightpos0 = calcShadingLPos(gstate.getUVLS0());
Vec3f lightpos1 = calcShadingLPos(gstate.getUVLS1());
uv[0] = (1.0f + Dot(lightpos0, worldnormal))/2.0f;
uv[1] = (1.0f + Dot(lightpos1, worldnormal))/2.0f;
@@ -446,7 +460,7 @@ void SoftwareTransform(
if (params->allowSeparateAlphaClear || (alphaMatchesColor && depthMatchesStencil)) {
result->color = transformed[1].color0_32;
// Need to rescale from a [0, 1] float. This is the final transformed value.
result->depth = ToScaledDepth((s16)(int)(transformed[1].z * 65535.0f));
result->depth = ToScaledDepthFromIntegerScale((int)(transformed[1].z * 65535.0f));
result->action = SW_CLEAR;
gpuStats.numClears++;
return;
+23 -102
View File
@@ -488,106 +488,23 @@ void DrawEngineCommon::ClearSplineBezierWeights() {
Spline3DWeight::weightsCache.Clear();
}
void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead) {
PROFILE_THIS_SCOPE("spline");
DispatchFlush();
// Specialize to make instance (to avoid link error).
template void DrawEngineCommon::SubmitCurve<BezierSurface>(const void *control_points, const void *indices, BezierSurface &surface, u32 vertType, int *bytesRead, const char *scope);
template void DrawEngineCommon::SubmitCurve<SplineSurface>(const void *control_points, const void *indices, SplineSurface &surface, u32 vertType, int *bytesRead, const char *scope);
// Real hardware seems to draw nothing when given < 4 either U or V.
if (count_u < 4 || count_v < 4)
return;
SimpleBufferManager managedBuf(decoded, DECODED_VERTEX_BUFFER_SIZE / 2);
int num_points = count_u * count_v;
u16 index_lower_bound = 0;
u16 index_upper_bound = num_points - 1;
IndexConverter ConvertIndex(vertType, indices);
if (indices)
GetIndexBounds(indices, num_points, vertType, &index_lower_bound, &index_upper_bound);
VertexDecoder *origVDecoder = GetVertexDecoder((vertType & 0xFFFFFF) | (gstate.getUVGenMode() << 24));
*bytesRead = num_points * origVDecoder->VertexSize();
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)managedBuf.Allocate(sizeof(SimpleVertex) * (index_upper_bound + 1));
u8 *temp_buffer = managedBuf.Allocate(sizeof(SimpleVertex) * num_points);
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
int vertexSize = vdecoder->VertexSize();
if (vertexSize != sizeof(SimpleVertex)) {
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, (int)sizeof(SimpleVertex));
}
// Make an array of pointers to the control points, to get rid of indices.
const SimpleVertex **points = (const SimpleVertex **)managedBuf.Allocate(sizeof(SimpleVertex *) * num_points);
for (int idx = 0; idx < num_points; idx++)
points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx);
OutputBuffers output;
output.vertices = (SimpleVertex *)(decoded + DECODED_VERTEX_BUFFER_SIZE / 2);
output.indices = decIndex;
output.count = 0;
SplineSurface surface;
surface.tess_u = tess_u;
surface.tess_v = tess_v;
surface.type_u = type_u;
surface.type_v = type_v;
surface.num_points_u = count_u;
surface.num_points_v = count_v;
surface.num_patches_u = count_u - 3;
surface.num_patches_v = count_v - 3;
surface.primType = prim_type;
surface.patchFacing = patchFacing;
surface.Init(DECODED_VERTEX_BUFFER_SIZE / 2 / vertexSize);
if (CanUseHardwareTessellation(prim_type)) {
HardwareTessellation(output, surface, origVertType, points, tessDataTransfer);
} else {
ControlPoints cpoints(points, num_points, managedBuf);
SoftwareTessellation(output, surface, origVertType, cpoints);
}
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
UVScale prevUVScale;
if ((origVertType & GE_VTYPE_TC_MASK) != 0) {
// We scaled during Normalize already so let's turn it off when drawing.
prevUVScale = gstate_c.uv;
gstate_c.uv.uScale = 1.0f;
gstate_c.uv.vScale = 1.0f;
gstate_c.uv.uOff = 0.0f;
gstate_c.uv.vOff = 0.0f;
}
uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode());
int generatedBytesRead;
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(prim_type), output.count, vertTypeID, &generatedBytesRead);
DispatchFlush();
if ((origVertType & GE_VTYPE_TC_MASK) != 0) {
gstate_c.uv = prevUVScale;
}
}
void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indices, int tess_u, int tess_v, int count_u, int count_v, GEPatchPrimType prim_type, bool computeNormals, bool patchFacing, u32 vertType, int *bytesRead) {
PROFILE_THIS_SCOPE("bezier");
template<class Surface>
void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indices, Surface &surface, u32 vertType, int *bytesRead, const char *scope) {
PROFILE_THIS_SCOPE(scope);
DispatchFlush();
// Real hardware seems to draw nothing when given < 4 either U or V.
// This would result in num_patches_u / num_patches_v being 0.
if (count_u < 4 || count_v < 4)
if (surface.num_points_u < 4 || surface.num_points_v < 4)
return;
SimpleBufferManager managedBuf(decoded, DECODED_VERTEX_BUFFER_SIZE / 2);
int num_points = count_u * count_v;
int num_points = surface.num_points_u * surface.num_points_v;
u16 index_lower_bound = 0;
u16 index_upper_bound = num_points - 1;
IndexConverter ConvertIndex(vertType, indices);
@@ -600,7 +517,16 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
// Simplify away bones and morph before proceeding
// There are normally not a lot of control points so just splitting decoded should be reasonably safe, although not great.
SimpleVertex *simplified_control_points = (SimpleVertex *)managedBuf.Allocate(sizeof(SimpleVertex) * (index_upper_bound + 1));
if (!simplified_control_points) {
ERROR_LOG(G3D, "Failed to allocate space for simplified control points, skipping curve draw");
return;
}
u8 *temp_buffer = managedBuf.Allocate(sizeof(SimpleVertex) * num_points);
if (!temp_buffer) {
ERROR_LOG(G3D, "Failed to allocate space for temp buffer, skipping curve draw");
return;
}
u32 origVertType = vertType;
vertType = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertType);
@@ -614,6 +540,10 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
// Make an array of pointers to the control points, to get rid of indices.
const SimpleVertex **points = (const SimpleVertex **)managedBuf.Allocate(sizeof(SimpleVertex *) * num_points);
if (!points) {
ERROR_LOG(G3D, "Failed to allocate space for control point pointers, skipping curve draw");
return;
}
for (int idx = 0; idx < num_points; idx++)
points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx);
@@ -622,18 +552,9 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
output.indices = decIndex;
output.count = 0;
BezierSurface surface;
surface.tess_u = tess_u;
surface.tess_v = tess_v;
surface.num_points_u = count_u;
surface.num_points_v = count_v;
surface.num_patches_u = (count_u - 1) / 3;
surface.num_patches_v = (count_v - 1) / 3;
surface.primType = prim_type;
surface.patchFacing = patchFacing;
surface.Init(DECODED_VERTEX_BUFFER_SIZE / 2 / vertexSize);
if (CanUseHardwareTessellation(prim_type)) {
if (CanUseHardwareTessellation(surface.primType)) {
HardwareTessellation(output, surface, origVertType, points, tessDataTransfer);
} else {
ControlPoints cpoints(points, num_points, managedBuf);
@@ -654,7 +575,7 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode());
int generatedBytesRead;
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(prim_type), output.count, vertTypeID, &generatedBytesRead);
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, gstate.getCullMode(), &generatedBytesRead);
DispatchFlush();
+11 -7
View File
@@ -642,9 +642,10 @@ void TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const c
}
void TextureCacheCommon::NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg) {
// Must be in VRAM so | 0x04000000 it is. Also, ignore memory mirrors.
// Mask to ignore the Z memory mirrors if the address is in VRAM.
// These checks are mainly to reduce scanning all textures.
const u32 addr = (address | 0x04000000) & 0x3F9FFFFF;
const u32 mirrorMask = 0x00600000;
const u32 addr = Memory::IsVRAMAddress(address) ? (address & ~mirrorMask) : address;
const u32 bpp = framebuffer->format == GE_FORMAT_8888 ? 4 : 2;
const u64 cacheKey = (u64)addr << 32;
// If it has a clut, those are the low 32 bits, so it'll be inside this range.
@@ -756,10 +757,13 @@ bool TextureCacheCommon::AttachFramebuffer(TexCacheEntry *entry, u32 address, Vi
AttachedFramebufferInfo fbInfo = { 0 };
const u64 mirrorMask = 0x00600000;
// Must be in VRAM so | 0x04000000 it is. Also, ignore memory mirrors.
const u32 addr = (address | 0x04000000) & 0x3FFFFFFF & ~mirrorMask;
const u32 texaddr = ((entry->addr + texaddrOffset) & ~mirrorMask);
const u32 mirrorMask = 0x00600000;
u32 addr = address & 0x3FFFFFFF;
u32 texaddr = entry->addr + texaddrOffset;
if (entry->addr & 0x04000000) {
addr &= ~mirrorMask;
texaddr &= ~mirrorMask;
}
const bool noOffset = texaddr == addr;
const bool exactMatch = noOffset && entry->format < 4;
const u32 w = 1 << ((entry->dim >> 0) & 0xf);
@@ -1002,7 +1006,7 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes) {
clutRenderOffset_ = MAX_CLUT_OFFSET;
for (size_t i = 0, n = fbCache_.size(); i < n; ++i) {
auto framebuffer = fbCache_[i];
const u32 fb_address = framebuffer->fb_address | 0x04000000;
const u32 fb_address = framebuffer->fb_address & 0x3FFFFFFF;
const u32 bpp = framebuffer->drawnFormat == GE_FORMAT_8888 ? 4 : 2;
u32 offset = clutFramebufAddr - fb_address;
+20 -26
View File
@@ -348,41 +348,36 @@ static inline u32 makecol(int r, int g, int b, int a) {
return (a << 24) | (r << 16) | (g << 8) | b;
}
static inline int mul_3_8(int c) {
// This is 3/8 * c = 4/8 * c - 1/8 * c.
return (c >> 1) - (c >> 3);
static inline int mix_2_3(int c1, int c2) {
return (c1 + c1 + c2) / 3;
}
// This could probably be done faster by decoding two or four blocks at a time with SSE/NEON.
void DXTDecoder::DecodeColors(const DXT1Block *src, bool ignore1bitAlpha) {
u16 c1 = src->color1;
u16 c2 = src->color2;
int red1 = Convert5To8(c1 & 0x1F);
int red2 = Convert5To8(c2 & 0x1F);
int green1 = Convert6To8((c1 >> 5) & 0x3F);
int green2 = Convert6To8((c2 >> 5) & 0x3F);
int blue1 = Convert5To8((c1 >> 11) & 0x1F);
int blue2 = Convert5To8((c2 >> 11) & 0x1F);
int red1 = (c1 << 3) & 0xF8;
int red2 = (c2 << 3) & 0xF8;
int green1 = (c1 >> 3) & 0xFC;
int green2 = (c2 >> 3) & 0xFC;
int blue1 = (c1 >> 8) & 0xF8;
int blue2 = (c2 >> 8) & 0xF8;
// Keep alpha zero for non-DXT1 to skip masking the colors.
int alpha = ignore1bitAlpha ? 0 : 255;
colors_[0] = makecol(red1, green1, blue1, alpha);
colors_[1] = makecol(red2, green2, blue2, alpha);
if (c1 > c2 || ignore1bitAlpha) {
int red3 = mul_3_8(red2 - red1);
int green3 = mul_3_8(green2 - green1);
int blue3 = mul_3_8(blue2 - blue1);
colors_[2] = makecol(red1 + red3, green1 + green3, blue1 + blue3, alpha);
colors_[3] = makecol(red2 - red3, green2 - green3, blue2 - blue3, alpha);
if (c1 > c2) {
colors_[2] = makecol(mix_2_3(red1, red2), mix_2_3(green1, green2), mix_2_3(blue1, blue2), alpha);
colors_[3] = makecol(mix_2_3(red2, red1), mix_2_3(green2, green1), mix_2_3(blue2, blue1), alpha);
} else {
// Average
int red3 = (red1 + red2 + 1) / 2;
int green3 = (green1 + green2 + 1) / 2;
int blue3 = (blue1 + blue2 + 1) / 2;
colors_[2] = makecol(red3, green3, blue3, 255);
// Color2 but transparent
colors_[3] = makecol(red2, green2, blue2, 0);
// Average - these are always left shifted, so no need to worry about ties.
int red3 = (red1 + red2) / 2;
int green3 = (green1 + green2) / 2;
int blue3 = (blue1 + blue2) / 2;
colors_[2] = makecol(red3, green3, blue3, alpha);
colors_[3] = makecol(0, 0, 0, 0);
}
}
@@ -390,13 +385,13 @@ static inline u8 lerp8(const DXT5Block *src, int n) {
// These weights translate alpha1/alpha2 to fixed 8.8 point, pre-divided by 7.
int weight1 = ((7 - n) << 8) / 7;
int weight2 = (n << 8) / 7;
return (u8)((src->alpha1 * weight1 + src->alpha2 * weight2) >> 8);
return (u8)((src->alpha1 * weight1 + src->alpha2 * weight2 + 255) >> 8);
}
static inline u8 lerp6(const DXT5Block *src, int n) {
int weight1 = ((5 - n) << 8) / 5;
int weight2 = (n << 8) / 5;
return (u8)((src->alpha1 * weight1 + src->alpha2 * weight2) >> 8);
return (u8)((src->alpha1 * weight1 + src->alpha2 * weight2 + 255) >> 8);
}
void DXTDecoder::DecodeAlphaDXT5(const DXT5Block *src) {
@@ -436,8 +431,7 @@ void DXTDecoder::WriteColorsDXT3(u32 *dst, const DXT3Block *src, int pitch, int
int colordata = src->color.lines[y];
u32 alphadata = src->alphaLines[y];
for (int x = 0; x < 4; x++) {
const u8 a4 = alphadata & 0xF;
dst[x] = colors_[colordata & 3] | (a4 << 24) | (a4 << 28);
dst[x] = colors_[colordata & 3] | (alphadata << 28);
colordata >>= 2;
alphadata >>= 4;
}
+2 -2
View File
@@ -49,7 +49,7 @@ void DoUnswizzleTex16Basic(const u8 *texptr, u32 *ydestp, int bxc, int byc, u32
#define DoReliableHash32 XXH32
#define DoReliableHash64 XXH64
#ifdef _M_X64
#if defined(_M_X64) || defined(ARM64)
#define DoReliableHash XXH64
typedef u64 ReliableHashType;
#else
@@ -58,7 +58,7 @@ typedef u32 ReliableHashType;
#endif
// For ARM64, NEON is mandatory, so we also statically link.
#elif PPSSPP_ARCH(ARM64)
#elif PPSSPP_ARCH(ARM64) || defined(ARM64)
#define DoQuickTexHash QuickTexHashNEON
#define StableQuickTexHash QuickTexHashNEON
#define DoUnswizzleTex16 DoUnswizzleTex16NEON
+3 -3
View File
@@ -107,9 +107,9 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
Vec3f lightDir(0, 0, 0);
if (type == GE_LIGHTTYPE_DIRECTIONAL)
toLight = Vec3f(&lpos[l * 3]); // lightdir is for spotlights
toLight = Vec3Packedf(&lpos[l * 3]); // lightdir is for spotlights
else
toLight = Vec3f(&lpos[l * 3]) - pos;
toLight = Vec3Packedf(&lpos[l * 3]) - pos;
bool doSpecular = gstate.isUsingSpecularLight(l);
bool poweredDiffuse = gstate.isUsingPoweredDiffuseLight(l);
@@ -139,7 +139,7 @@ void Lighter::Light(float colorOut0[4], float colorOut1[4], const float colorIn[
break;
case GE_LIGHTTYPE_SPOT:
case GE_LIGHTTYPE_UNKNOWN:
lightDir = Vec3f(&ldir[l * 3]);
lightDir = Vec3Packedf(&ldir[l * 3]);
angle = Dot(toLight.Normalized(), lightDir.Normalized());
if (angle >= lcutoff[l])
lightScale = clamp(1.0f / (latt[l * 3] + latt[l * 3 + 1] * distanceToLight + latt[l * 3 + 2] * distanceToLight*distanceToLight), 0.0f, 1.0f) * powf(angle, lconv[l]);
+16 -15
View File
@@ -33,21 +33,22 @@
#define SHADERLOG
#endif
static const char *depalVShaderHLSL =
"struct VS_IN {\n"
" float3 a_position : POSITION;\n"
" float2 a_texcoord0 : TEXCOORD0;\n"
"};\n"
"struct VS_OUT {\n"
" float2 Texcoord : TEXCOORD0;\n"
" float4 Position : SV_Position;\n"
"};\n"
"VS_OUT main(VS_IN input) {\n"
" VS_OUT output;\n"
" output.Texcoord = input.a_texcoord0;\n"
" output.Position = float4(input.a_position, 1.0);\n"
" return output;\n"
"}\n";
static const char *depalVShaderHLSL = R"(
struct VS_IN {
float3 a_position : POSITION;
float2 a_texcoord0 : TEXCOORD0;
};
struct VS_OUT {
float2 Texcoord : TEXCOORD0;
float4 Position : SV_Position;
};
VS_OUT main(VS_IN input) {
VS_OUT output;
output.Texcoord = input.a_texcoord0;
output.Position = float4(input.a_position, 1.0);
return output;
}
)";
static const D3D11_INPUT_ELEMENT_DESC g_DepalVertexElements[] = {
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, },
+3 -1
View File
@@ -137,6 +137,8 @@ void DrawEngineD3D11::DestroyDeviceObjects() {
ClearTrackedVertexArrays();
ClearInputLayoutMap();
delete tessDataTransferD3D11;
tessDataTransferD3D11 = nullptr;
tessDataTransfer = nullptr;
delete pushVerts_;
delete pushInds_;
depthStencilCache_.Iterate([&](const uint64_t &key, ID3D11DepthStencilState *ds) {
@@ -655,7 +657,7 @@ rotateVBO:
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
if (g_Config.bBlockTransferGPU && (gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
if ((gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
+3 -6
View File
@@ -512,9 +512,6 @@ static void CopyPixelDepthOnly(u32 *dstp, const u32 *srcp, size_t c) {
}
void FramebufferManagerD3D11::BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) {
if (g_Config.bDisableSlowFramebufEffects) {
return;
}
bool matchingDepthBuffer = src->z_address == dst->z_address && src->z_stride != 0 && dst->z_stride != 0;
bool matchingSize = src->width == dst->width && src->height == dst->height;
bool matchingRenderSize = src->renderWidth == dst->renderWidth && src->renderHeight == dst->renderHeight;
@@ -537,7 +534,7 @@ void FramebufferManagerD3D11::BindFramebufferAsColorTexture(int stage, VirtualFr
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
// Let's just not bother with the copy in that case.
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
if (GPUStepping::IsStepping() || g_Config.bDisableSlowFramebufEffects) {
if (GPUStepping::IsStepping()) {
skipCopy = true;
}
// Currently rendering to this framebuffer. Need to make a copy.
@@ -553,7 +550,7 @@ void FramebufferManagerD3D11::BindFramebufferAsColorTexture(int stage, VirtualFr
} else {
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
}
} else if (framebuffer != currentRenderVfb_) {
} else if (framebuffer != currentRenderVfb_ || (flags & BINDFBCOLOR_FORCE_SELF) != 0) {
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::FB_COLOR_BIT, 0);
} else {
ERROR_LOG_REPORT_ONCE(d3d11SelfTexture, G3D, "Attempting to texture from target (src=%08x / target=%08x / flags=%d)", framebuffer->fb_address, currentRenderVfb_->fb_address, flags);
@@ -687,7 +684,7 @@ void FramebufferManagerD3D11::PackDepthbuffer(VirtualFramebuffer *vfb, int x, in
return;
}
const u32 z_address = (0x04000000) | vfb->z_address;
const u32 z_address = vfb->z_address;
// TODO
}
+1 -1
View File
@@ -77,7 +77,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
stockD3D11.Create(device_);
shaderManagerD3D11_ = new ShaderManagerD3D11(device_, context_, featureLevel);
shaderManagerD3D11_ = new ShaderManagerD3D11(draw, device_, context_, featureLevel);
framebufferManagerD3D11_ = new FramebufferManagerD3D11(draw);
framebufferManager_ = framebufferManagerD3D11_;
textureCacheD3D11_ = new TextureCacheD3D11(draw);
+5 -4
View File
@@ -27,6 +27,7 @@
#include "math/math_util.h"
#include "math/dataconv.h"
#include "file/vfs.h"
#include "thin3d/thin3d.h"
#include "util/text/utf8.h"
#include "Common/Common.h"
#include "Core/Config.h"
@@ -96,9 +97,9 @@ ShaderManagerD3D11::ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext
memset(&ub_lights, 0, sizeof(ub_lights));
memset(&ub_bones, 0, sizeof(ub_bones));
INFO_LOG(G3D, "sizeof(ub_base): %d", (int)sizeof(ub_base));
INFO_LOG(G3D, "sizeof(ub_lights): %d", (int)sizeof(ub_lights));
INFO_LOG(G3D, "sizeof(ub_bones): %d", (int)sizeof(ub_bones));
static_assert(sizeof(ub_base) <= 512, "ub_base grew too big");
static_assert(sizeof(ub_lights) <= 512, "ub_lights grew too big");
static_assert(sizeof(ub_bones) <= 384, "ub_bones grew too big");
D3D11_BUFFER_DESC desc{sizeof(ub_base), D3D11_USAGE_DYNAMIC, D3D11_BIND_CONSTANT_BUFFER, D3D11_CPU_ACCESS_WRITE };
ASSERT_SUCCESS(device_->CreateBuffer(&desc, nullptr, &push_base));
@@ -195,7 +196,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
if (gstate_c.IsDirty(DIRTY_FRAGMENTSHADER_STATE)) {
gstate_c.Clean(DIRTY_FRAGMENTSHADER_STATE);
ComputeFragmentShaderID(&FSID);
ComputeFragmentShaderID(&FSID, draw_->GetBugs());
} else {
FSID = lastFSID_;
}
+1 -1
View File
@@ -81,7 +81,7 @@ class D3D11PushBuffer;
class ShaderManagerD3D11 : public ShaderManagerCommon {
public:
ShaderManagerD3D11(ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel);
ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel);
~ShaderManagerD3D11();
void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, bool useHWTransform);
+1 -1
View File
@@ -223,7 +223,7 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
#endif
// Let's not write to alpha if stencil isn't enabled.
if (!gstate.isStencilTestEnabled()) {
if (IsStencilTestOutputDisabled()) {
amask = false;
} else {
// If the stencil type is set to KEEP, we shouldn't write to the stencil/alpha channel.
+2 -1
View File
@@ -71,6 +71,7 @@ VS_OUT main(VS_IN In) {
// TODO : If SV_StencilRef is available (D3D11.3) then this can be done in a single pass.
bool FramebufferManagerD3D11::NotifyStencilUpload(u32 addr, int size, bool skipZero) {
addr &= 0x3FFFFFFF;
if (!MayIntersectFramebuffer(addr)) {
return false;
}
@@ -78,7 +79,7 @@ bool FramebufferManagerD3D11::NotifyStencilUpload(u32 addr, int size, bool skipZ
VirtualFramebuffer *dstBuffer = 0;
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
if (MaskedEqual(vfb->fb_address, addr)) {
if (vfb->fb_address == addr) {
dstBuffer = vfb;
}
}
+20 -19
View File
@@ -277,7 +277,7 @@ public:
};
TextureShaderApplierD3D11(ID3D11DeviceContext *context, ID3D11PixelShader *pshader, ID3D11Buffer *dynamicBuffer, float bufferW, float bufferH, int renderW, int renderH, float xoff, float yoff)
: context_(context), pshader_(pshader), bufferW_(bufferW), bufferH_(bufferH), renderW_(renderW), renderH_(renderH) {
: context_(context), pshader_(pshader), vbuffer_(dynamicBuffer), bufferW_(bufferW), bufferH_(bufferH), renderW_(renderW), renderH_(renderH) {
static const Pos pos[4] = {
{ -1, 1, 0 },
{ 1, 1, 0 },
@@ -297,11 +297,6 @@ public:
verts_[i].pos.y += yoff;
verts_[i].uv = uv[i];
}
D3D11_MAPPED_SUBRESOURCE map;
context->Map(dynamicBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, &verts_[0], 4 * 5 * sizeof(float));
context->Unmap(dynamicBuffer, 0);
vbuffer_ = dynamicBuffer;
}
void ApplyBounds(const KnownVertexBounds &bounds, u32 uoff, u32 voff, float xoff, float yoff) {
@@ -320,28 +315,34 @@ public:
const float left = u1 * invHalfWidth - 1.0f + xoff;
const float right = u2 * invHalfWidth - 1.0f + xoff;
const float top = v1 * invHalfHeight - 1.0f + yoff;
const float bottom = v2 * invHalfHeight - 1.0f + yoff;
const float top = (bufferH_ - v1) * invHalfHeight - 1.0f + yoff;
const float bottom = (bufferH_ - v2) * invHalfHeight - 1.0f + yoff;
float z = 0.0f;
// Points are: BL, BR, TL, TR.
verts_[0].pos = Pos(left, bottom, z);
verts_[1].pos = Pos(right, bottom, z);
verts_[2].pos = Pos(left, top, z);
verts_[3].pos = Pos(right, top, z);
verts_[0].pos = Pos(left, top, z);
verts_[1].pos = Pos(right, top, z);
verts_[2].pos = Pos(left, bottom, z);
verts_[3].pos = Pos(right, bottom, z);
// And also the UVs, same order.
const float uvleft = u1 * invWidth;
const float uvright = u2 * invWidth;
const float uvtop = v1 * invHeight;
const float uvbottom = v2 * invHeight;
verts_[0].uv = UV(uvleft, uvbottom);
verts_[1].uv = UV(uvright, uvbottom);
verts_[2].uv = UV(uvleft, uvtop);
verts_[3].uv = UV(uvright, uvtop);
verts_[0].uv = UV(uvleft, uvtop);
verts_[1].uv = UV(uvright, uvtop);
verts_[2].uv = UV(uvleft, uvbottom);
verts_[3].uv = UV(uvright, uvbottom);
// We need to reapply the texture next time since we cropped UV.
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
}
D3D11_MAPPED_SUBRESOURCE map;
context_->Map(vbuffer_, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
memcpy(map.pData, &verts_[0], 4 * 5 * sizeof(float));
context_->Unmap(vbuffer_, 0);
}
void Use(ID3D11VertexShader *vshader, ID3D11InputLayout *decl) {
@@ -398,11 +399,11 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra
shaderApply.ApplyBounds(gstate_c.vertBounds, gstate_c.curTextureXOffset, gstate_c.curTextureYOffset, xoff, yoff);
shaderApply.Use(depalShaderCache_->GetDepalettizeVertexShader(), depalShaderCache_->GetInputLayout());
draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE });
context_->PSSetShaderResources(3, 1, &clutTexture);
context_->PSSetSamplers(3, 1, &stockD3D11.samplerPoint2DWrap);
framebufferManagerD3D11_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY);
framebufferManagerD3D11_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY | BINDFBCOLOR_FORCE_SELF);
context_->PSSetSamplers(0, 1, &stockD3D11.samplerPoint2DWrap);
draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE });
shaderApply.Shade();
framebufferManagerD3D11_->RebindFramebuffer();
Loaded 100 of 339 files, more files were not shown because too many files have changed in this diff. Show more