Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 04714c26d7 | |||
| e57c9be21f | |||
| 930b10878a | |||
| d8a9618a62 | |||
| 0ca23681fc | |||
| d72afe2ac0 | |||
| f89e096617 | |||
| d28e0f51fa | |||
| 0079a09305 | |||
| 7763f62f93 | |||
| 29c1772097 | |||
| 1f4b5f7a73 | |||
| a21690f3f7 | |||
| 6a02f655aa | |||
| c272931f23 | |||
| ad7e5c84d4 | |||
| a4fcd02ee7 | |||
| da4640a016 | |||
| e193aa3f53 | |||
| 25174afa79 | |||
| f2df941e8d | |||
| e0af4cdf98 | |||
| 406d298457 | |||
| 14a1181a97 | |||
| c27c76ed43 | |||
| e8855ed0fc | |||
| f98bf1025f | |||
| a8674a7b86 | |||
| c6ba7a228d | |||
| c12eb814b4 | |||
| 928e9c09aa | |||
| 2bd903e021 | |||
| 7d1dca4c98 | |||
| 5865a10885 | |||
| a6e5b84d1f | |||
| 5a4e89b901 | |||
| 140f953b6a | |||
| 8ea749c1ca | |||
| 479605b3e5 | |||
| 9c5ed4408d | |||
| a7fe6dc232 | |||
| 811bff009e | |||
| 4514b80b3e | |||
| 7daea551c0 | |||
| 8434630dcc | |||
| c6a963c48e | |||
| 8272f53cf9 | |||
| 7236393114 | |||
| c7ed7d9427 | |||
| 977ceb4056 | |||
| 7d763f060e | |||
| 778f86989a | |||
| b19fe55f84 | |||
| 4f09f0aea4 | |||
| 69f38355ed | |||
| b1eada6079 | |||
| 442e48ef4c | |||
| 8ae7154541 | |||
| 44f10d9b9f |
+34
-1
@@ -6,7 +6,16 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/find-module
|
||||
include(DownloadExternals)
|
||||
include(CMakeDependentOption)
|
||||
|
||||
project(yuzu)
|
||||
if (APPLE)
|
||||
project(yuzu C CXX ASM)
|
||||
option(OSX_USE_DEFAULT_SEARCH_PATH "Don't prioritize system library paths" OFF)
|
||||
else()
|
||||
project(yuzu)
|
||||
endif()
|
||||
|
||||
# Pin build to minimum supported OSX version.
|
||||
# 10.15 supports metal 3 so has additional unsupported MVK extensions
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.14.0" CACHE STRING "")
|
||||
|
||||
# Set bundled sdl2/qt as dependent options.
|
||||
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
||||
@@ -414,6 +423,30 @@ if (APPLE)
|
||||
# Umbrella framework for everything GUI-related
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
set(PLATFORM_LIBRARIES ${COCOA_LIBRARY} ${IOKIT_LIBRARY} ${COREVIDEO_LIBRARY})
|
||||
if(NOT OSX_USE_DEFAULT_SEARCH_PATH)
|
||||
# Hack up the path to prioritize the path to built-in OS libraries to
|
||||
# increase the chance of not depending on a bunch of copies of them
|
||||
# installed by MacPorts, Fink, Homebrew, etc, and ending up copying
|
||||
# them into the bundle. Since we optionally depend on libraries which
|
||||
# are not part of OS X (ffmpeg, etc.), however, don't remove the default
|
||||
# path entirely as was done in a previous version of this file. This is
|
||||
# still kinda evil, since it defeats the user's path settings...
|
||||
# See http://www.cmake.org/cmake/help/v3.0/command/find_program.html
|
||||
list(APPEND CMAKE_PREFIX_PATH "/usr")
|
||||
endif()
|
||||
|
||||
# Linker flags.
|
||||
# Drop unreachable code and data.
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip,-dead_strip_dylibs")
|
||||
|
||||
find_library(APPKIT_LIBRARY AppKit)
|
||||
find_library(APPSERV_LIBRARY ApplicationServices)
|
||||
find_library(CARBON_LIBRARY Carbon)
|
||||
find_library(COCOA_LIBRARY Cocoa)
|
||||
find_library(COREFOUNDATION_LIBRARY CoreFoundation)
|
||||
find_library(CORESERV_LIBRARY CoreServices)
|
||||
find_library(FOUNDATION_LIBRARY Foundation)
|
||||
find_library(IOK_LIBRARY IOKit)
|
||||
elseif (WIN32)
|
||||
# WSAPoll and SHGetKnownFolderPath (AppData/Roaming) didn't exist before WinNT 6.x (Vista)
|
||||
add_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
# This module can be used in two different ways.
|
||||
#
|
||||
# When invoked as `cmake -P PostprocessBundle.cmake`, it fixes up an
|
||||
# application folder to be standalone. It bundles all required libraries from
|
||||
# the system and fixes up library IDs. Any additional shared libraries, like
|
||||
# plugins, that are found under Contents/MacOS/ will be made standalone as well.
|
||||
#
|
||||
# When called with `include(PostprocessBundle)`, it defines a helper
|
||||
# function `postprocess_bundle` that sets up the command form of the
|
||||
# module as a post-build step.
|
||||
|
||||
if(CMAKE_GENERATOR)
|
||||
# Being called as include(PostprocessBundle), so define a helper function.
|
||||
set(_POSTPROCESS_BUNDLE_MODULE_LOCATION "${CMAKE_CURRENT_LIST_FILE}")
|
||||
function(postprocess_bundle target)
|
||||
add_custom_command(TARGET ${target} POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -DBUNDLE_PATH="$<TARGET_FILE_DIR:${target}>/../.."
|
||||
-P "${_POSTPROCESS_BUNDLE_MODULE_LOCATION}"
|
||||
)
|
||||
endfunction()
|
||||
return()
|
||||
endif()
|
||||
|
||||
get_filename_component(BUNDLE_PATH "${BUNDLE_PATH}" REALPATH)
|
||||
message(STATUS "Fixing up application bundle: ${BUNDLE_PATH}")
|
||||
|
||||
# Make sure to fix up any additional shared libraries (like plugins) that are
|
||||
# needed.
|
||||
file(GLOB_RECURSE extra_libs "${BUNDLE_PATH}/Contents/MacOS/*.dylib")
|
||||
|
||||
# BundleUtilities doesn't support DYLD_FALLBACK_LIBRARY_PATH behavior, which
|
||||
# makes it sometimes break on libraries that do weird things with @rpath. Specify
|
||||
# equivalent search directories until https://gitlab.kitware.com/cmake/cmake/issues/16625
|
||||
# is fixed and in our minimum CMake version.
|
||||
set(extra_dirs "/usr/local/lib" "/lib" "/usr/lib")
|
||||
|
||||
# BundleUtilities is overly verbose, so disable most of its messages
|
||||
function(message)
|
||||
if(NOT ARGV MATCHES "^STATUS;")
|
||||
_message(${ARGV})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
include(BundleUtilities)
|
||||
set(BU_CHMOD_BUNDLE_ITEMS ON)
|
||||
fixup_bundle("${BUNDLE_PATH}" "${extra_libs}" "${extra_dirs}")
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"file_format_version": "1.0.0",
|
||||
"ICD": {
|
||||
"library_path": "../../../lib/libMoltenVK.dylib",
|
||||
"api_version": "1.0.0"
|
||||
}
|
||||
}
|
||||
+468
@@ -0,0 +1,468 @@
|
||||
/*
|
||||
* mvk_datatypes.h
|
||||
*
|
||||
* Copyright (c) 2015-2020 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This file contains functions for converting between Vulkan and Metal data types.
|
||||
*
|
||||
* The functions here are used internally by MoltenVK, and are exposed here
|
||||
* as a convenience for use elsewhere within applications using MoltenVK.
|
||||
*/
|
||||
|
||||
#ifndef __mvkDataTypes_h_
|
||||
#define __mvkDataTypes_h_ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "mvk_vulkan.h"
|
||||
|
||||
#import <Metal/Metal.h>
|
||||
#import <CoreGraphics/CoreGraphics.h>
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Image properties
|
||||
|
||||
#pragma mark Texture formats
|
||||
|
||||
/** Enumerates the data type of a format. */
|
||||
typedef enum {
|
||||
kMVKFormatNone, /**< Format type is unknown. */
|
||||
kMVKFormatColorHalf, /**< A 16-bit floating point color. */
|
||||
kMVKFormatColorFloat, /**< A 32-bit floating point color. */
|
||||
kMVKFormatColorInt8, /**< A signed 8-bit integer color. */
|
||||
kMVKFormatColorUInt8, /**< An unsigned 8-bit integer color. */
|
||||
kMVKFormatColorInt16, /**< A signed 16-bit integer color. */
|
||||
kMVKFormatColorUInt16, /**< An unsigned 16-bit integer color. */
|
||||
kMVKFormatColorInt32, /**< A signed 32-bit integer color. */
|
||||
kMVKFormatColorUInt32, /**< An unsigned 32-bit integer color. */
|
||||
kMVKFormatDepthStencil, /**< A depth and stencil value. */
|
||||
kMVKFormatCompressed, /**< A block-compressed color. */
|
||||
} MVKFormatType;
|
||||
|
||||
/** Returns whether the VkFormat is supported by this implementation. */
|
||||
bool mvkVkFormatIsSupported(VkFormat vkFormat);
|
||||
|
||||
/** Returns whether the MTLPixelFormat is supported by this implementation. */
|
||||
bool mvkMTLPixelFormatIsSupported(MTLPixelFormat mtlFormat);
|
||||
|
||||
/** Returns the format type corresponding to the specified Vulkan VkFormat, */
|
||||
MVKFormatType mvkFormatTypeFromVkFormat(VkFormat vkFormat);
|
||||
|
||||
/** Returns the format type corresponding to the specified Metal MTLPixelFormat, */
|
||||
MVKFormatType mvkFormatTypeFromMTLPixelFormat(MTLPixelFormat mtlFormat);
|
||||
|
||||
/**
|
||||
* Returns the Metal MTLPixelFormat corresponding to the specified Vulkan VkFormat,
|
||||
* or returns MTLPixelFormatInvalid if no corresponding MTLPixelFormat exists.
|
||||
*
|
||||
* Not all MTLPixelFormats returned by this function are supported by all GPU's,
|
||||
* and, internally, MoltenVK may substitute and use a different MTLPixelFormat than
|
||||
* is returned by this function for a particular Vulkan VkFormat value.
|
||||
*
|
||||
* Not all macOS GPU's support the MTLPixelFormatDepth24Unorm_Stencil8 pixel format.
|
||||
* Even though this function will return that value when passed the corresponding
|
||||
* VkFormat value, internally, MoltenVK will use the MTLPixelFormatDepth32Float_Stencil8
|
||||
* instead when a GPU does not support the MTLPixelFormatDepth24Unorm_Stencil8 pixel format.
|
||||
* On an macOS device that has more than one GPU, one of the GPU's may support the
|
||||
* MTLPixelFormatDepth24Unorm_Stencil8 pixel format while another may not.
|
||||
*/
|
||||
MTLPixelFormat mvkMTLPixelFormatFromVkFormat(VkFormat vkFormat);
|
||||
|
||||
/**
|
||||
* Returns the Vulkan VkFormat corresponding to the specified Metal MTLPixelFormat,
|
||||
* or returns VK_FORMAT_UNDEFINED if no corresponding VkFormat exists.
|
||||
*/
|
||||
VkFormat mvkVkFormatFromMTLPixelFormat(MTLPixelFormat mtlFormat);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a texel block of the specified Vulkan format.
|
||||
* For uncompressed formats, the returned value corresponds to the size in bytes of a single texel.
|
||||
*/
|
||||
uint32_t mvkVkFormatBytesPerBlock(VkFormat vkFormat);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a texel block of the specified Metal format.
|
||||
* For uncompressed formats, the returned value corresponds to the size in bytes of a single texel.
|
||||
*/
|
||||
uint32_t mvkMTLPixelFormatBytesPerBlock(MTLPixelFormat mtlFormat);
|
||||
|
||||
/**
|
||||
* Returns the size of the compression block, measured in texels for a Vulkan format.
|
||||
* The returned value will be {1, 1} for non-compressed formats.
|
||||
*/
|
||||
VkExtent2D mvkVkFormatBlockTexelSize(VkFormat vkFormat);
|
||||
|
||||
/**
|
||||
* Returns the size of the compression block, measured in texels for a Metal format.
|
||||
* The returned value will be {1, 1} for non-compressed formats.
|
||||
*/
|
||||
VkExtent2D mvkMTLPixelFormatBlockTexelSize(MTLPixelFormat mtlFormat);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a texel of the specified Vulkan format.
|
||||
* The returned value may be fractional for certain compressed formats.
|
||||
*/
|
||||
float mvkVkFormatBytesPerTexel(VkFormat vkFormat);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a texel of the specified Metal format.
|
||||
* The returned value may be fractional for certain compressed formats.
|
||||
*/
|
||||
float mvkMTLPixelFormatBytesPerTexel(MTLPixelFormat mtlFormat);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a row of texels of the specified Vulkan format.
|
||||
*
|
||||
* For compressed formats, this takes into consideration the compression block size,
|
||||
* and texelsPerRow should specify the width in texels, not blocks. The result is rounded
|
||||
* up if texelsPerRow is not an integer multiple of the compression block width.
|
||||
*/
|
||||
size_t mvkVkFormatBytesPerRow(VkFormat vkFormat, uint32_t texelsPerRow);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a row of texels of the specified Metal format.
|
||||
*
|
||||
* For compressed formats, this takes into consideration the compression block size,
|
||||
* and texelsPerRow should specify the width in texels, not blocks. The result is rounded
|
||||
* up if texelsPerRow is not an integer multiple of the compression block width.
|
||||
*/
|
||||
size_t mvkMTLPixelFormatBytesPerRow(MTLPixelFormat mtlFormat, uint32_t texelsPerRow);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a texture layer of the specified Vulkan format.
|
||||
*
|
||||
* For compressed formats, this takes into consideration the compression block size,
|
||||
* and texelRowsPerLayer should specify the height in texels, not blocks. The result is
|
||||
* rounded up if texelRowsPerLayer is not an integer multiple of the compression block height.
|
||||
*/
|
||||
size_t mvkVkFormatBytesPerLayer(VkFormat vkFormat, size_t bytesPerRow, uint32_t texelRowsPerLayer);
|
||||
|
||||
/**
|
||||
* Returns the size, in bytes, of a texture layer of the specified Metal format.
|
||||
* For compressed formats, this takes into consideration the compression block size,
|
||||
* and texelRowsPerLayer should specify the height in texels, not blocks. The result is
|
||||
* rounded up if texelRowsPerLayer is not an integer multiple of the compression block height.
|
||||
*/
|
||||
size_t mvkMTLPixelFormatBytesPerLayer(MTLPixelFormat mtlFormat, size_t bytesPerRow, uint32_t texelRowsPerLayer);
|
||||
|
||||
/** Returns the default properties for the specified Vulkan format. */
|
||||
VkFormatProperties mvkVkFormatProperties(VkFormat vkFormat);
|
||||
|
||||
/** Returns the name of the specified Vulkan format. */
|
||||
const char* mvkVkFormatName(VkFormat vkFormat);
|
||||
|
||||
/** Returns the name of the specified Metal pixel format. */
|
||||
const char* mvkMTLPixelFormatName(MTLPixelFormat mtlFormat);
|
||||
|
||||
/**
|
||||
* Returns the MTLClearColor value corresponding to the color value in the VkClearValue,
|
||||
* extracting the color value that is VkFormat for the VkFormat.
|
||||
*/
|
||||
MTLClearColor mvkMTLClearColorFromVkClearValue(VkClearValue vkClearValue,
|
||||
VkFormat vkFormat);
|
||||
|
||||
/** Returns the Metal depth value corresponding to the depth value in the specified VkClearValue. */
|
||||
double mvkMTLClearDepthFromVkClearValue(VkClearValue vkClearValue);
|
||||
|
||||
/** Returns the Metal stencil value corresponding to the stencil value in the specified VkClearValue. */
|
||||
uint32_t mvkMTLClearStencilFromVkClearValue(VkClearValue vkClearValue);
|
||||
|
||||
/** Returns whether the specified Metal MTLPixelFormat can be used as a depth format. */
|
||||
bool mvkMTLPixelFormatIsDepthFormat(MTLPixelFormat mtlFormat);
|
||||
|
||||
/** Returns whether the specified Metal MTLPixelFormat can be used as a stencil format. */
|
||||
bool mvkMTLPixelFormatIsStencilFormat(MTLPixelFormat mtlFormat);
|
||||
|
||||
/** Returns whether the specified Metal MTLPixelFormat is a PVRTC format. */
|
||||
bool mvkMTLPixelFormatIsPVRTCFormat(MTLPixelFormat mtlFormat);
|
||||
|
||||
/** Returns the Metal texture type from the specified Vulkan image properties. */
|
||||
MTLTextureType mvkMTLTextureTypeFromVkImageType(VkImageType vkImageType,
|
||||
uint32_t arraySize,
|
||||
bool isMultisample);
|
||||
|
||||
/** Returns the Vulkan image type from the Metal texture type. */
|
||||
VkImageType mvkVkImageTypeFromMTLTextureType(MTLTextureType mtlTextureType);
|
||||
|
||||
/** Returns the Metal MTLTextureType corresponding to the Vulkan VkImageViewType. */
|
||||
MTLTextureType mvkMTLTextureTypeFromVkImageViewType(VkImageViewType vkImageViewType, bool isMultisample);
|
||||
|
||||
/** Returns the Metal texture usage from the Vulkan image usage taking into considertion usage limits for the pixel format. */
|
||||
MTLTextureUsage mvkMTLTextureUsageFromVkImageUsageFlags(VkImageUsageFlags vkImageUsageFlags, MTLPixelFormat mtlPixFmt);
|
||||
|
||||
/** Returns the Vulkan image usage from the Metal texture usage and format. */
|
||||
VkImageUsageFlags mvkVkImageUsageFlagsFromMTLTextureUsage(MTLTextureUsage mtlUsage, MTLPixelFormat mtlFormat);
|
||||
|
||||
/**
|
||||
* Returns the numeric sample count corresponding to the specified Vulkan sample count flag.
|
||||
*
|
||||
* The specified flags value should have only one bit set, otherwise an invalid numeric value will be returned.
|
||||
*/
|
||||
uint32_t mvkSampleCountFromVkSampleCountFlagBits(VkSampleCountFlagBits vkSampleCountFlag);
|
||||
|
||||
/** Returns the Vulkan bit flags corresponding to the numeric sample count, which must be a PoT value. */
|
||||
VkSampleCountFlagBits mvkVkSampleCountFlagBitsFromSampleCount(NSUInteger sampleCount);
|
||||
|
||||
/** Returns the Metal texture swizzle from the Vulkan component swizzle. */
|
||||
MTLTextureSwizzle mvkMTLTextureSwizzleFromVkComponentSwizzle(VkComponentSwizzle vkSwizzle);
|
||||
|
||||
/** Returns all four Metal texture swizzles from the Vulkan component mapping. */
|
||||
MTLTextureSwizzleChannels mvkMTLTextureSwizzleChannelsFromVkComponentMapping(VkComponentMapping vkMapping);
|
||||
|
||||
|
||||
#pragma mark Mipmaps
|
||||
|
||||
/**
|
||||
* Returns the number of mipmap levels available to an image with the specified side dimension.
|
||||
*
|
||||
* If the specified dimension is a power-of-two, the value returned is (log2(dim) + 1).
|
||||
* If the specified dimension is NOT a power-of-two, the value returned is 0, indicating
|
||||
* that the image cannot support mipmaps.
|
||||
*/
|
||||
uint32_t mvkMipmapLevels(uint32_t dim);
|
||||
|
||||
/**
|
||||
* Returns the number of mipmap levels available to an image with the specified extent.
|
||||
*
|
||||
* If each dimension in the specified extent is a power-of-two, the value returned
|
||||
* is MAX(log2(dim) + 1) across both dimensions. If either dimension in the specified
|
||||
* extent is NOT a power-of-two, the value returned is 1, indicating that the image
|
||||
* cannot support mipmaps, and that only the base mip level can be used.
|
||||
*/
|
||||
uint32_t mvkMipmapLevels2D(VkExtent2D extent);
|
||||
|
||||
/**
|
||||
* Returns the number of mipmap levels available to an image with the specified extent.
|
||||
*
|
||||
* If each dimension in the specified extent is a power-of-two, the value returned
|
||||
* is MAX(log2(dim) + 1) across all dimensions. If either dimension in the specified
|
||||
* extent is NOT a power-of-two, the value returned is 1, indicating that the image
|
||||
* cannot support mipmaps, and that only the base mip level can be used.
|
||||
*/
|
||||
uint32_t mvkMipmapLevels3D(VkExtent3D extent);
|
||||
|
||||
/**
|
||||
* Returns the size of the specified zero-based mipmap level,
|
||||
* when the size of the base level is the specified size.
|
||||
*/
|
||||
VkExtent2D mvkMipmapLevelSizeFromBaseSize2D(VkExtent2D baseSize, uint32_t level);
|
||||
|
||||
/**
|
||||
* Returns the size of the specified zero-based mipmap level,
|
||||
* when the size of the base level is the specified size.
|
||||
*/
|
||||
VkExtent3D mvkMipmapLevelSizeFromBaseSize3D(VkExtent3D baseSize, uint32_t level);
|
||||
|
||||
/**
|
||||
* Returns the size of the mipmap base level, when the size of
|
||||
* the specified zero-based mipmap level is the specified size.
|
||||
*/
|
||||
VkExtent2D mvkMipmapBaseSizeFromLevelSize2D(VkExtent2D levelSize, uint32_t level);
|
||||
|
||||
/**
|
||||
* Returns the size of the mipmap base level, when the size of
|
||||
* the specified zero-based mipmap level is the specified size.
|
||||
*/
|
||||
VkExtent3D mvkMipmapBaseSizeFromLevelSize3D(VkExtent3D levelSize, uint32_t level);
|
||||
|
||||
|
||||
#pragma mark Samplers
|
||||
|
||||
/**
|
||||
* Returns the Metal MTLSamplerAddressMode corresponding to the specified Vulkan VkSamplerAddressMode,
|
||||
* or returns MTLSamplerAddressModeMirrorClampToEdge if no corresponding MTLSamplerAddressMode exists.
|
||||
*/
|
||||
MTLSamplerAddressMode mvkMTLSamplerAddressModeFromVkSamplerAddressMode(VkSamplerAddressMode vkMode);
|
||||
|
||||
#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
|
||||
/**
|
||||
* Returns the Metal MTLSamplerBorderColor corresponding to the specified Vulkan VkBorderColor,
|
||||
* or returns MTLSamplerBorderColorTransparentBlack if no corresponding MTLSamplerBorderColor exists.
|
||||
*/
|
||||
MTLSamplerBorderColor mvkMTLSamplerBorderColorFromVkBorderColor(VkBorderColor vkColor);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the Metal MTLSamplerMinMagFilter corresponding to the specified Vulkan VkFilter,
|
||||
* or returns MTLSamplerMinMagFilterNearest if no corresponding MTLSamplerMinMagFilter exists.
|
||||
*/
|
||||
MTLSamplerMinMagFilter mvkMTLSamplerMinMagFilterFromVkFilter(VkFilter vkFilter);
|
||||
|
||||
/**
|
||||
* Returns the Metal MTLSamplerMipFilter corresponding to the specified Vulkan VkSamplerMipmapMode,
|
||||
* or returns MTLSamplerMipFilterNotMipmapped if no corresponding MTLSamplerMipFilter exists.
|
||||
*/
|
||||
MTLSamplerMipFilter mvkMTLSamplerMipFilterFromVkSamplerMipmapMode(VkSamplerMipmapMode vkMode);
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Render pipeline
|
||||
|
||||
/** Identifies a particular shading stage in a pipeline. */
|
||||
typedef enum {
|
||||
kMVKShaderStageVertex = 0,
|
||||
kMVKShaderStageTessCtl,
|
||||
kMVKShaderStageTessEval,
|
||||
kMVKShaderStageFragment,
|
||||
kMVKShaderStageCompute,
|
||||
kMVKShaderStageMax
|
||||
} MVKShaderStage;
|
||||
|
||||
/** Returns the Metal MTLColorWriteMask corresponding to the specified Vulkan VkColorComponentFlags. */
|
||||
MTLColorWriteMask mvkMTLColorWriteMaskFromVkChannelFlags(VkColorComponentFlags vkWriteFlags);
|
||||
|
||||
/** Returns the Metal MTLBlendOperation corresponding to the specified Vulkan VkBlendOp. */
|
||||
MTLBlendOperation mvkMTLBlendOperationFromVkBlendOp(VkBlendOp vkBlendOp);
|
||||
|
||||
/** Returns the Metal MTLBlendFactor corresponding to the specified Vulkan VkBlendFactor. */
|
||||
MTLBlendFactor mvkMTLBlendFactorFromVkBlendFactor(VkBlendFactor vkBlendFactor);
|
||||
|
||||
/**
|
||||
* Returns the Metal MTLVertexFormat corresponding to the specified
|
||||
* Vulkan VkFormat as used as a vertex attribute format.
|
||||
*/
|
||||
MTLVertexFormat mvkMTLVertexFormatFromVkFormat(VkFormat vkFormat);
|
||||
|
||||
/** Returns the Metal MTLVertexStepFunction corresponding to the specified Vulkan VkVertexInputRate. */
|
||||
MTLVertexStepFunction mvkMTLVertexStepFunctionFromVkVertexInputRate(VkVertexInputRate vkVtxStep);
|
||||
|
||||
/** Returns the Metal MTLPrimitiveType corresponding to the specified Vulkan VkPrimitiveTopology. */
|
||||
MTLPrimitiveType mvkMTLPrimitiveTypeFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);
|
||||
|
||||
/** Returns the Metal MTLPrimitiveTopologyClass corresponding to the specified Vulkan VkPrimitiveTopology. */
|
||||
MTLPrimitiveTopologyClass mvkMTLPrimitiveTopologyClassFromVkPrimitiveTopology(VkPrimitiveTopology vkTopology);
|
||||
|
||||
/** Returns the Metal MTLTriangleFillMode corresponding to the specified Vulkan VkPolygonMode, */
|
||||
MTLTriangleFillMode mvkMTLTriangleFillModeFromVkPolygonMode(VkPolygonMode vkFillMode);
|
||||
|
||||
/** Returns the Metal MTLLoadAction corresponding to the specified Vulkan VkAttachmentLoadOp. */
|
||||
MTLLoadAction mvkMTLLoadActionFromVkAttachmentLoadOp(VkAttachmentLoadOp vkLoadOp);
|
||||
|
||||
/** Returns the Metal MTLStoreAction corresponding to the specified Vulkan VkAttachmentStoreOp. */
|
||||
MTLStoreAction mvkMTLStoreActionFromVkAttachmentStoreOp(VkAttachmentStoreOp vkStoreOp, bool hasResolveAttachment);
|
||||
|
||||
/** Returns the Metal MTLViewport corresponding to the specified Vulkan VkViewport. */
|
||||
MTLViewport mvkMTLViewportFromVkViewport(VkViewport vkViewport);
|
||||
|
||||
/** Returns the Metal MTLScissorRect corresponding to the specified Vulkan VkRect2D. */
|
||||
MTLScissorRect mvkMTLScissorRectFromVkRect2D(VkRect2D vkRect);
|
||||
|
||||
/** Returns the Metal MTLCompareFunction corresponding to the specified Vulkan VkCompareOp, */
|
||||
MTLCompareFunction mvkMTLCompareFunctionFromVkCompareOp(VkCompareOp vkOp);
|
||||
|
||||
/** Returns the Metal MTLStencilOperation corresponding to the specified Vulkan VkStencilOp, */
|
||||
MTLStencilOperation mvkMTLStencilOperationFromVkStencilOp(VkStencilOp vkOp);
|
||||
|
||||
/** Returns the Metal MTLCullMode corresponding to the specified Vulkan VkCullModeFlags, */
|
||||
MTLCullMode mvkMTLCullModeFromVkCullModeFlags(VkCullModeFlags vkCull);
|
||||
|
||||
/** Returns the Metal MTLWinding corresponding to the specified Vulkan VkFrontFace, */
|
||||
MTLWinding mvkMTLWindingFromVkFrontFace(VkFrontFace vkWinding);
|
||||
|
||||
/** Returns the Metal MTLIndexType corresponding to the specified Vulkan VkIndexType, */
|
||||
MTLIndexType mvkMTLIndexTypeFromVkIndexType(VkIndexType vkIdxType);
|
||||
|
||||
/** Returns the size, in bytes, of a vertex index of the specified type. */
|
||||
size_t mvkMTLIndexTypeSizeInBytes(MTLIndexType mtlIdxType);
|
||||
|
||||
/** Returns the MoltenVK MVKShaderStage corresponding to the specified Vulkan VkShaderStageFlagBits. */
|
||||
MVKShaderStage mvkShaderStageFromVkShaderStageFlagBits(VkShaderStageFlagBits vkStage);
|
||||
|
||||
/** Returns the Vulkan VkShaderStageFlagBits corresponding to the specified MoltenVK MVKShaderStage. */
|
||||
VkShaderStageFlagBits mvkVkShaderStageFlagBitsFromMVKShaderStage(MVKShaderStage mvkStage);
|
||||
|
||||
/** Returns the Metal MTLWinding corresponding to the specified SPIR-V spv::ExecutionMode. */
|
||||
MTLWinding mvkMTLWindingFromSpvExecutionMode(uint32_t spvMode);
|
||||
|
||||
/** Returns the Metal MTLTessellationPartitionMode corresponding to the specified SPIR-V spv::ExecutionMode. */
|
||||
MTLTessellationPartitionMode mvkMTLTessellationPartitionModeFromSpvExecutionMode(uint32_t spvMode);
|
||||
|
||||
/**
|
||||
* Returns the combination of Metal MTLRenderStage bits corresponding to the specified Vulkan VkPiplineStageFlags,
|
||||
* taking into consideration whether the barrier is to be placed before or after the specified pipeline stages.
|
||||
*/
|
||||
MTLRenderStages mvkMTLRenderStagesFromVkPipelineStageFlags(VkPipelineStageFlags vkStages, bool placeBarrierBefore);
|
||||
|
||||
/** Returns the combination of Metal MTLBarrierScope bits corresponding to the specified Vulkan VkAccessFlags. */
|
||||
MTLBarrierScope mvkMTLBarrierScopeFromVkAccessFlags(VkAccessFlags vkAccess);
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Geometry conversions
|
||||
|
||||
/** Returns a VkExtent2D that corresponds to the specified CGSize. */
|
||||
static inline VkExtent2D mvkVkExtent2DFromCGSize(CGSize cgSize) {
|
||||
VkExtent2D vkExt;
|
||||
vkExt.width = cgSize.width;
|
||||
vkExt.height = cgSize.height;
|
||||
return vkExt;
|
||||
}
|
||||
|
||||
/** Returns a Metal MTLOrigin constructed from a VkOffset3D. */
|
||||
static inline MTLOrigin mvkMTLOriginFromVkOffset3D(VkOffset3D vkOffset) {
|
||||
return MTLOriginMake(vkOffset.x, vkOffset.y, vkOffset.z);
|
||||
}
|
||||
|
||||
/** Returns a Vulkan VkOffset3D constructed from a Metal MTLOrigin. */
|
||||
static inline VkOffset3D mvkVkOffset3DFromMTLSize(MTLOrigin mtlOrigin) {
|
||||
return { (int32_t)mtlOrigin.x, (int32_t)mtlOrigin.y, (int32_t)mtlOrigin.z };
|
||||
}
|
||||
|
||||
/** Returns a Metal MTLSize constructed from a VkExtent3D. */
|
||||
static inline MTLSize mvkMTLSizeFromVkExtent3D(VkExtent3D vkExtent) {
|
||||
return MTLSizeMake(vkExtent.width, vkExtent.height, vkExtent.depth);
|
||||
}
|
||||
|
||||
/** Returns a Vulkan VkExtent3D constructed from a Metal MTLSize. */
|
||||
static inline VkExtent3D mvkVkExtent3DFromMTLSize(MTLSize mtlSize) {
|
||||
return { (uint32_t)mtlSize.width, (uint32_t)mtlSize.height, (uint32_t)mtlSize.depth };
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Memory options
|
||||
|
||||
/** Macro indicating the Vulkan memory type bits corresponding to Metal private memory (not host visible). */
|
||||
#define MVK_VK_MEMORY_TYPE_METAL_PRIVATE (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
|
||||
/** Macro indicating the Vulkan memory type bits corresponding to Metal shared memory (host visible and coherent). */
|
||||
#define MVK_VK_MEMORY_TYPE_METAL_SHARED (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||
|
||||
/** Macro indicating the Vulkan memory type bits corresponding to Metal managed memory (host visible and non-coherent). */
|
||||
#define MVK_VK_MEMORY_TYPE_METAL_MANAGED (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
|
||||
|
||||
/** Macro indicating the Vulkan memory type bits corresponding to Metal memoryless memory (not host visible and lazily allocated). */
|
||||
#define MVK_VK_MEMORY_TYPE_METAL_MEMORYLESS (VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
|
||||
|
||||
/** Returns the Metal storage mode corresponding to the specified Vulkan memory flags. */
|
||||
MTLStorageMode mvkMTLStorageModeFromVkMemoryPropertyFlags(VkMemoryPropertyFlags vkFlags);
|
||||
|
||||
/** Returns the Metal CPU cache mode corresponding to the specified Vulkan memory flags. */
|
||||
MTLCPUCacheMode mvkMTLCPUCacheModeFromVkMemoryPropertyFlags(VkMemoryPropertyFlags vkFlags);
|
||||
|
||||
/** Returns the Metal resource option flags corresponding to the Metal storage mode and cache mode. */
|
||||
MTLResourceOptions mvkMTLResourceOptions(MTLStorageMode mtlStorageMode, MTLCPUCacheMode mtlCPUCacheMode);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* mvk_vulkan.h
|
||||
*
|
||||
* Copyright (c) 2015-2020 The Brenwill Workshop Ltd. (http://www.brenwill.com)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* This is a convenience header file that loads vulkan.h with the appropriate Vulkan platform extensions.
|
||||
*
|
||||
* This header automatically enables the VK_EXT_metal_surface Vulkan extension.
|
||||
*
|
||||
* When building for iOS, this header also automatically enables the obsolete VK_MVK_ios_surface Vulkan extension.
|
||||
* When building for macOS, this header also automatically enables the obsolete VK_MVK_macos_surface Vulkan extension.
|
||||
* Both of these extensions are obsolete. Consider using the portable VK_EXT_metal_surface extension instead.
|
||||
*/
|
||||
|
||||
#ifndef __mvk_vulkan_h_
|
||||
#define __mvk_vulkan_h_ 1
|
||||
|
||||
|
||||
#include <Availability.h>
|
||||
|
||||
#define VK_USE_PLATFORM_METAL_EXT 1
|
||||
|
||||
#ifdef __IPHONE_OS_VERSION_MAX_ALLOWED
|
||||
# define VK_USE_PLATFORM_IOS_MVK 1
|
||||
#endif
|
||||
|
||||
#ifdef __MAC_OS_X_VERSION_MAX_ALLOWED
|
||||
# define VK_USE_PLATFORM_MACOS_MVK 1
|
||||
#endif
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan-portability/vk_extx_portability_subset.h>
|
||||
|
||||
#endif
|
||||
+1034
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,76 @@
|
||||
#ifndef VK_EXTX_PORTABILITY_SUBSET_H_
|
||||
#define VK_EXTX_PORTABILITY_SUBSET_H_ 1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Copyright (c) 2018 The Khronos Group Inc.
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Please Note: This extension is currently defined as "EXTX", meaning "multivendor experimental".
|
||||
That means the definition of this extension is in active development, and may break compatibility
|
||||
between point releases (defined as any increment of VK_EXTX_PORTABILITY_SUBSET_SPEC_VERSION).
|
||||
You are free to explore the extension and provide feedback, but it is not recommended to use this
|
||||
extension for shipping applications, particularly applications that require the driver implementing this
|
||||
extension to be linked dynamically and potentially "dropped-in" to the application execution environment.
|
||||
*/
|
||||
|
||||
#include "vulkan/vulkan.h"
|
||||
|
||||
#define VK_EXTX_PORTABILITY_SUBSET_SPEC_VERSION 1
|
||||
#define VK_EXTX_PORTABILITY_SUBSET_EXTENSION_NAME "VK_EXTX_portability_subset"
|
||||
|
||||
#define VK_EXTX_PORTABILITY_SUBSET_EXTENSION_ID 164
|
||||
// See enum_offset() from https://www.khronos.org/registry/vulkan/specs/1.1/styleguide.html#_assigning_extension_token_values
|
||||
#define VK_EXTX_PORTABILITY_SUBSET_STYPE_ID(x) \
|
||||
((VkStructureType)(1000000000 + 1000 * (VK_EXTX_PORTABILITY_SUBSET_EXTENSION_ID - 1) + x))
|
||||
#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_EXTX VK_EXTX_PORTABILITY_SUBSET_STYPE_ID(0)
|
||||
#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_PROPERTIES_EXTX VK_EXTX_PORTABILITY_SUBSET_STYPE_ID(1)
|
||||
#define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_VIEW_SUPPORT_EXTX VK_EXTX_PORTABILITY_SUBSET_STYPE_ID(2)
|
||||
|
||||
typedef struct VkPhysicalDevicePortabilitySubsetFeaturesEXTX {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkBool32 triangleFans;
|
||||
VkBool32 separateStencilMaskRef;
|
||||
VkBool32 events;
|
||||
VkBool32 standardImageViews;
|
||||
VkBool32 samplerMipLodBias;
|
||||
} VkPhysicalDevicePortabilitySubsetFeaturesEXTX;
|
||||
|
||||
typedef struct VkPhysicalDevicePortabilitySubsetPropertiesEXTX {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
uint32_t minVertexInputBindingStrideAlignment;
|
||||
} VkPhysicalDevicePortabilitySubsetPropertiesEXTX;
|
||||
|
||||
typedef struct VkPhysicalDeviceImageViewSupportEXTX {
|
||||
VkStructureType sType;
|
||||
void* pNext;
|
||||
VkImageViewCreateFlags flags;
|
||||
VkImageViewType viewType;
|
||||
VkFormat format;
|
||||
VkComponentMapping components;
|
||||
VkImageAspectFlags aspectMask;
|
||||
} VkPhysicalDeviceImageViewSupportEXTX;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // VK_EXTX_PORTABILITY_SUBSET_H_
|
||||
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
@@ -62,10 +62,6 @@ else()
|
||||
-Wno-unused-parameter
|
||||
)
|
||||
|
||||
if (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
add_compile_options("-stdlib=libc++")
|
||||
endif()
|
||||
|
||||
# Set file offset size to 64 bits.
|
||||
#
|
||||
# On modern Unixes, this is typically already the case. The lone exception is
|
||||
|
||||
@@ -606,11 +606,11 @@ endif()
|
||||
create_target_directory_groups(core)
|
||||
|
||||
target_link_libraries(core PUBLIC common PRIVATE audio_core video_core)
|
||||
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus unicorn)
|
||||
target_link_libraries(core PUBLIC Boost::boost PRIVATE fmt::fmt nlohmann_json::nlohmann_json mbedtls Opus::Opus unicorn zip)
|
||||
|
||||
if (YUZU_ENABLE_BOXCAT)
|
||||
target_compile_definitions(core PRIVATE -DYUZU_ENABLE_BOXCAT)
|
||||
target_link_libraries(core PRIVATE httplib nlohmann_json::nlohmann_json zip)
|
||||
target_link_libraries(core PRIVATE httplib nlohmann_json::nlohmann_json)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
|
||||
@@ -62,7 +62,7 @@ public:
|
||||
case Dynarmic::A32::Exception::Breakpoint:
|
||||
break;
|
||||
}
|
||||
LOG_CRITICAL(HW_GPU, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
|
||||
LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
|
||||
static_cast<std::size_t>(exception), pc, MemoryReadCode(pc));
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
||||
@@ -98,8 +98,8 @@ public:
|
||||
}
|
||||
[[fallthrough]];
|
||||
default:
|
||||
ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:X})",
|
||||
static_cast<std::size_t>(exception), pc);
|
||||
ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
|
||||
static_cast<std::size_t>(exception), pc, MemoryReadCode(pc));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ VirtualDir MiiModel() {
|
||||
out->AddFile(std::make_shared<ArrayVfsFile<MiiModelData::SHAPE_MID.size()>>(
|
||||
MiiModelData::SHAPE_MID, "ShapeMid.dat"));
|
||||
|
||||
return std::move(out);
|
||||
return out;
|
||||
}
|
||||
|
||||
} // namespace FileSys::SystemArchive
|
||||
|
||||
@@ -23,7 +23,7 @@ VirtualFile PackBFTTF(const std::array<u8, Size>& data, const std::string& name)
|
||||
|
||||
std::vector<u8> bfttf(Size + sizeof(u64));
|
||||
|
||||
u64 offset = 0;
|
||||
size_t offset = 0;
|
||||
Service::NS::EncryptSharedFont(vec, bfttf, offset);
|
||||
return std::make_shared<VectorVfsFile>(std::move(bfttf), name);
|
||||
}
|
||||
|
||||
@@ -14,12 +14,7 @@ namespace Core::Frontend {
|
||||
|
||||
/// Information for the Graphics Backends signifying what type of screen pointer is in
|
||||
/// WindowInformation
|
||||
enum class WindowSystemType {
|
||||
Headless,
|
||||
Windows,
|
||||
X11,
|
||||
Wayland,
|
||||
};
|
||||
enum class WindowSystemType { Headless, Windows, X11, Wayland, MacOS };
|
||||
|
||||
/**
|
||||
* Represents a drawing context that supports graphics operations.
|
||||
@@ -156,6 +151,14 @@ public:
|
||||
return window_info;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns drawing area raw pointer
|
||||
* Unsafe version for MoltenVK to modify pointer
|
||||
*/
|
||||
void*& GetRenderSurface() {
|
||||
return window_info.render_surface;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the framebuffer layout (width, height, and screen regions)
|
||||
* @note This method is thread-safe
|
||||
|
||||
@@ -104,7 +104,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa
|
||||
// Ensure that we don't leave anything un-freed
|
||||
auto group_guard = detail::ScopeExit([&] {
|
||||
for (const auto& it : page_list.Nodes()) {
|
||||
const auto min_num_pages{std::min(
|
||||
const auto min_num_pages{std::min<size_t>(
|
||||
it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)};
|
||||
chosen_manager.Free(it.GetAddress(), min_num_pages);
|
||||
}
|
||||
@@ -165,7 +165,7 @@ ResultCode MemoryManager::Free(PageLinkedList& page_list, std::size_t num_pages,
|
||||
|
||||
// Free all of the pages
|
||||
for (const auto& it : page_list.Nodes()) {
|
||||
const auto min_num_pages{std::min(
|
||||
const auto min_num_pages{std::min<size_t>(
|
||||
it.GetNumPages(), (chosen_manager.GetEndAddress() - it.GetAddress()) / PageSize)};
|
||||
chosen_manager.Free(it.GetAddress(), min_num_pages);
|
||||
}
|
||||
|
||||
@@ -44,6 +44,218 @@ static constexpr u32 SanitizeJPEGSize(std::size_t size) {
|
||||
return static_cast<u32>(std::min(size, max_jpeg_image_size));
|
||||
}
|
||||
|
||||
class IManagerForSystemService final : public ServiceFramework<IManagerForSystemService> {
|
||||
public:
|
||||
explicit IManagerForSystemService(Common::UUID user_id)
|
||||
: ServiceFramework("IManagerForSystemService") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CheckAvailability"},
|
||||
{1, nullptr, "GetAccountId"},
|
||||
{2, nullptr, "EnsureIdTokenCacheAsync"},
|
||||
{3, nullptr, "LoadIdTokenCache"},
|
||||
{100, nullptr, "SetSystemProgramIdentification"},
|
||||
{101, nullptr, "RefreshNotificationTokenAsync"}, // 7.0.0+
|
||||
{110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+
|
||||
{111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+
|
||||
{112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0
|
||||
{113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+
|
||||
{120, nullptr, "GetNintendoAccountId"},
|
||||
{121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+
|
||||
{130, nullptr, "GetNintendoAccountUserResourceCache"},
|
||||
{131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"},
|
||||
{132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"},
|
||||
{133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+
|
||||
{134, nullptr, "RefreshNintendoAccountVerificationUrlCache"}, // 9.0.0+
|
||||
{135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+
|
||||
{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
|
||||
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
|
||||
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
|
||||
{150, nullptr, "CreateAuthorizationRequest"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
// 3.0.0+
|
||||
class IFloatingRegistrationRequest final : public ServiceFramework<IFloatingRegistrationRequest> {
|
||||
public:
|
||||
explicit IFloatingRegistrationRequest(Common::UUID user_id)
|
||||
: ServiceFramework("IFloatingRegistrationRequest") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetSessionId"},
|
||||
{12, nullptr, "GetAccountId"},
|
||||
{13, nullptr, "GetLinkedNintendoAccountId"},
|
||||
{14, nullptr, "GetNickname"},
|
||||
{15, nullptr, "GetProfileImage"},
|
||||
{21, nullptr, "LoadIdTokenCache"},
|
||||
{100, nullptr, "RegisterUser"}, // [1.0.0-3.0.2] RegisterAsync
|
||||
{101, nullptr, "RegisterUserWithUid"}, // [1.0.0-3.0.2] RegisterWithUidAsync
|
||||
{102, nullptr, "RegisterNetworkServiceAccountAsync"}, // 4.0.0+
|
||||
{103, nullptr, "RegisterNetworkServiceAccountWithUidAsync"}, // 4.0.0+
|
||||
{110, nullptr, "SetSystemProgramIdentification"},
|
||||
{111, nullptr, "EnsureIdTokenCacheAsync"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class IAdministrator final : public ServiceFramework<IAdministrator> {
|
||||
public:
|
||||
explicit IAdministrator(Common::UUID user_id) : ServiceFramework("IAdministrator") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "CheckAvailability"},
|
||||
{1, nullptr, "GetAccountId"},
|
||||
{2, nullptr, "EnsureIdTokenCacheAsync"},
|
||||
{3, nullptr, "LoadIdTokenCache"},
|
||||
{100, nullptr, "SetSystemProgramIdentification"},
|
||||
{101, nullptr, "RefreshNotificationTokenAsync"}, // 7.0.0+
|
||||
{110, nullptr, "GetServiceEntryRequirementCache"}, // 4.0.0+
|
||||
{111, nullptr, "InvalidateServiceEntryRequirementCache"}, // 4.0.0+
|
||||
{112, nullptr, "InvalidateTokenCache"}, // 4.0.0 - 6.2.0
|
||||
{113, nullptr, "GetServiceEntryRequirementCacheForOnlinePlay"}, // 6.1.0+
|
||||
{120, nullptr, "GetNintendoAccountId"},
|
||||
{121, nullptr, "CalculateNintendoAccountAuthenticationFingerprint"}, // 9.0.0+
|
||||
{130, nullptr, "GetNintendoAccountUserResourceCache"},
|
||||
{131, nullptr, "RefreshNintendoAccountUserResourceCacheAsync"},
|
||||
{132, nullptr, "RefreshNintendoAccountUserResourceCacheAsyncIfSecondsElapsed"},
|
||||
{133, nullptr, "GetNintendoAccountVerificationUrlCache"}, // 9.0.0+
|
||||
{134, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsync"}, // 9.0.0+
|
||||
{135, nullptr, "RefreshNintendoAccountVerificationUrlCacheAsyncIfSecondsElapsed"}, // 9.0.0+
|
||||
{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
|
||||
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
|
||||
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
|
||||
{150, nullptr, "CreateAuthorizationRequest"},
|
||||
{200, nullptr, "IsRegistered"},
|
||||
{201, nullptr, "RegisterAsync"},
|
||||
{202, nullptr, "UnregisterAsync"},
|
||||
{203, nullptr, "DeleteRegistrationInfoLocally"},
|
||||
{220, nullptr, "SynchronizeProfileAsync"},
|
||||
{221, nullptr, "UploadProfileAsync"},
|
||||
{222, nullptr, "SynchronizaProfileAsyncIfSecondsElapsed"},
|
||||
{250, nullptr, "IsLinkedWithNintendoAccount"},
|
||||
{251, nullptr, "CreateProcedureToLinkWithNintendoAccount"},
|
||||
{252, nullptr, "ResumeProcedureToLinkWithNintendoAccount"},
|
||||
{255, nullptr, "CreateProcedureToUpdateLinkageStateOfNintendoAccount"},
|
||||
{256, nullptr, "ResumeProcedureToUpdateLinkageStateOfNintendoAccount"},
|
||||
{260, nullptr, "CreateProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+
|
||||
{261, nullptr, "ResumeProcedureToLinkNnidWithNintendoAccount"}, // 3.0.0+
|
||||
{280, nullptr, "ProxyProcedureToAcquireApplicationAuthorizationForNintendoAccount"},
|
||||
{290, nullptr, "GetRequestForNintendoAccountUserResourceView"}, // 8.0.0+
|
||||
{300, nullptr, "TryRecoverNintendoAccountUserStateAsync"}, // 6.0.0+
|
||||
{400, nullptr, "IsServiceEntryRequirementCacheRefreshRequiredForOnlinePlay"}, // 6.1.0+
|
||||
{401, nullptr, "RefreshServiceEntryRequirementCacheForOnlinePlayAsync"}, // 6.1.0+
|
||||
{900, nullptr, "GetAuthenticationInfoForWin"}, // 9.0.0+
|
||||
{901, nullptr, "ImportAsyncForWin"}, // 9.0.0+
|
||||
{997, nullptr, "DebugUnlinkNintendoAccountAsync"},
|
||||
{998, nullptr, "DebugSetAvailabilityErrorDetail"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class IAuthorizationRequest final : public ServiceFramework<IAuthorizationRequest> {
|
||||
public:
|
||||
explicit IAuthorizationRequest(Common::UUID user_id)
|
||||
: ServiceFramework("IAuthorizationRequest") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetSessionId"},
|
||||
{10, nullptr, "InvokeWithoutInteractionAsync"},
|
||||
{19, nullptr, "IsAuthorized"},
|
||||
{20, nullptr, "GetAuthorizationCode"},
|
||||
{21, nullptr, "GetIdToken"},
|
||||
{22, nullptr, "GetState"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class IOAuthProcedure final : public ServiceFramework<IOAuthProcedure> {
|
||||
public:
|
||||
explicit IOAuthProcedure(Common::UUID user_id) : ServiceFramework("IOAuthProcedure") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "PrepareAsync"},
|
||||
{1, nullptr, "GetRequest"},
|
||||
{2, nullptr, "ApplyResponse"},
|
||||
{3, nullptr, "ApplyResponseAsync"},
|
||||
{10, nullptr, "Suspend"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
// 3.0.0+
|
||||
class IOAuthProcedureForExternalNsa final : public ServiceFramework<IOAuthProcedureForExternalNsa> {
|
||||
public:
|
||||
explicit IOAuthProcedureForExternalNsa(Common::UUID user_id)
|
||||
: ServiceFramework("IOAuthProcedureForExternalNsa") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "PrepareAsync"},
|
||||
{1, nullptr, "GetRequest"},
|
||||
{2, nullptr, "ApplyResponse"},
|
||||
{3, nullptr, "ApplyResponseAsync"},
|
||||
{10, nullptr, "Suspend"},
|
||||
{100, nullptr, "GetAccountId"},
|
||||
{101, nullptr, "GetLinkedNintendoAccountId"},
|
||||
{102, nullptr, "GetNickname"},
|
||||
{103, nullptr, "GetProfileImage"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class IOAuthProcedureForNintendoAccountLinkage final
|
||||
: public ServiceFramework<IOAuthProcedureForNintendoAccountLinkage> {
|
||||
public:
|
||||
explicit IOAuthProcedureForNintendoAccountLinkage(Common::UUID user_id)
|
||||
: ServiceFramework("IOAuthProcedureForNintendoAccountLinkage") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "PrepareAsync"},
|
||||
{1, nullptr, "GetRequest"},
|
||||
{2, nullptr, "ApplyResponse"},
|
||||
{3, nullptr, "ApplyResponseAsync"},
|
||||
{10, nullptr, "Suspend"},
|
||||
{100, nullptr, "GetRequestWithTheme"},
|
||||
{101, nullptr, "IsNetworkServiceAccountReplaced"},
|
||||
{199, nullptr, "GetUrlForIntroductionOfExtraMembership"}, // 2.0.0 - 5.1.0
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class INotifier final : public ServiceFramework<INotifier> {
|
||||
public:
|
||||
explicit INotifier(Common::UUID user_id) : ServiceFramework("INotifier") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetSystemEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class IProfileCommon : public ServiceFramework<IProfileCommon> {
|
||||
public:
|
||||
explicit IProfileCommon(const char* name, bool editor_commands, Common::UUID user_id,
|
||||
@@ -226,6 +438,54 @@ public:
|
||||
: IProfileCommon("IProfileEditor", true, user_id, profile_manager) {}
|
||||
};
|
||||
|
||||
class IAsyncContext final : public ServiceFramework<IAsyncContext> {
|
||||
public:
|
||||
explicit IAsyncContext(Common::UUID user_id) : ServiceFramework("IAsyncContext") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetSystemEvent"},
|
||||
{1, nullptr, "Cancel"},
|
||||
{2, nullptr, "HasDone"},
|
||||
{3, nullptr, "GetResult"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class ISessionObject final : public ServiceFramework<ISessionObject> {
|
||||
public:
|
||||
explicit ISessionObject(Common::UUID user_id) : ServiceFramework("ISessionObject") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{999, nullptr, "Dummy"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class IGuestLoginRequest final : public ServiceFramework<IGuestLoginRequest> {
|
||||
public:
|
||||
explicit IGuestLoginRequest(Common::UUID) : ServiceFramework("IGuestLoginRequest") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetSessionId"},
|
||||
{11, nullptr, "Unknown"}, // 1.0.0 - 2.3.0 (the name is blank on Switchbrew)
|
||||
{12, nullptr, "GetAccountId"},
|
||||
{13, nullptr, "GetLinkedNintendoAccountId"},
|
||||
{14, nullptr, "GetNickname"},
|
||||
{15, nullptr, "GetProfileImage"},
|
||||
{21, nullptr, "LoadIdTokenCache"}, // 3.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class IManagerForApplication final : public ServiceFramework<IManagerForApplication> {
|
||||
public:
|
||||
explicit IManagerForApplication(Common::UUID user_id)
|
||||
@@ -265,6 +525,87 @@ private:
|
||||
Common::UUID user_id;
|
||||
};
|
||||
|
||||
// 6.0.0+
|
||||
class IAsyncNetworkServiceLicenseKindContext final
|
||||
: public ServiceFramework<IAsyncNetworkServiceLicenseKindContext> {
|
||||
public:
|
||||
explicit IAsyncNetworkServiceLicenseKindContext(Common::UUID user_id)
|
||||
: ServiceFramework("IAsyncNetworkServiceLicenseKindContext") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetSystemEvent"},
|
||||
{1, nullptr, "Cancel"},
|
||||
{2, nullptr, "HasDone"},
|
||||
{3, nullptr, "GetResult"},
|
||||
{4, nullptr, "GetNetworkServiceLicenseKind"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
// 8.0.0+
|
||||
class IOAuthProcedureForUserRegistration final
|
||||
: public ServiceFramework<IOAuthProcedureForUserRegistration> {
|
||||
public:
|
||||
explicit IOAuthProcedureForUserRegistration(Common::UUID user_id)
|
||||
: ServiceFramework("IOAuthProcedureForUserRegistration") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "PrepareAsync"},
|
||||
{1, nullptr, "GetRequest"},
|
||||
{2, nullptr, "ApplyResponse"},
|
||||
{3, nullptr, "ApplyResponseAsync"},
|
||||
{10, nullptr, "Suspend"},
|
||||
{100, nullptr, "GetAccountId"},
|
||||
{101, nullptr, "GetLinkedNintendoAccountId"},
|
||||
{102, nullptr, "GetNickname"},
|
||||
{103, nullptr, "GetProfileImage"},
|
||||
{110, nullptr, "RegisterUserAsync"},
|
||||
{111, nullptr, "GetUid"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
class DAUTH_O final : public ServiceFramework<DAUTH_O> {
|
||||
public:
|
||||
explicit DAUTH_O(Common::UUID) : ServiceFramework("dauth:o") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "EnsureAuthenticationTokenCacheAsync"}, // [5.0.0-5.1.0] GeneratePostData
|
||||
{1, nullptr, "LoadAuthenticationTokenCache"}, // 6.0.0+
|
||||
{2, nullptr, "InvalidateAuthenticationTokenCache"}, // 6.0.0+
|
||||
{10, nullptr, "EnsureEdgeTokenCacheAsync"}, // 6.0.0+
|
||||
{11, nullptr, "LoadEdgeTokenCache"}, // 6.0.0+
|
||||
{12, nullptr, "InvalidateEdgeTokenCache"}, // 6.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
// 6.0.0+
|
||||
class IAsyncResult final : public ServiceFramework<IAsyncResult> {
|
||||
public:
|
||||
explicit IAsyncResult(Common::UUID user_id) : ServiceFramework("IAsyncResult") {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "GetResult"},
|
||||
{1, nullptr, "Cancel"},
|
||||
{2, nullptr, "IsAvailable"},
|
||||
{3, nullptr, "GetSystemEvent"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
};
|
||||
|
||||
void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_ACC, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
|
||||
@@ -13,8 +13,8 @@ ACC_AA::ACC_AA(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
|
||||
{0, nullptr, "EnsureCacheAsync"},
|
||||
{1, nullptr, "LoadCache"},
|
||||
{2, nullptr, "GetDeviceAccountId"},
|
||||
{50, nullptr, "RegisterNotificationTokenAsync"},
|
||||
{51, nullptr, "UnregisterNotificationTokenAsync"},
|
||||
{50, nullptr, "RegisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0
|
||||
{51, nullptr, "UnregisterNotificationTokenAsync"}, // 1.0.0 - 6.2.0
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
}
|
||||
|
||||
@@ -17,28 +17,28 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
|
||||
{3, &ACC_SU::ListOpenUsers, "ListOpenUsers"},
|
||||
{4, &ACC_SU::GetLastOpenedUser, "GetLastOpenedUser"},
|
||||
{5, &ACC_SU::GetProfile, "GetProfile"},
|
||||
{6, nullptr, "GetProfileDigest"},
|
||||
{6, nullptr, "GetProfileDigest"}, // 3.0.0+
|
||||
{50, &ACC_SU::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
||||
{51, &ACC_SU::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
||||
{60, nullptr, "ListOpenContextStoredUsers"},
|
||||
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||
{60, nullptr, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0
|
||||
{99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+
|
||||
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||
{101, nullptr, "GetUserStateChangeNotifier"},
|
||||
{102, nullptr, "GetBaasAccountManagerForSystemService"},
|
||||
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||
{104, nullptr, "GetProfileUpdateNotifier"},
|
||||
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||
{106, nullptr, "GetProfileSyncNotifier"},
|
||||
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+
|
||||
{106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+
|
||||
{110, nullptr, "StoreSaveDataThumbnail"},
|
||||
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||
{112, nullptr, "LoadSaveDataThumbnail"},
|
||||
{113, nullptr, "GetSaveDataThumbnailExistence"},
|
||||
{120, nullptr, "ListOpenUsersInApplication"},
|
||||
{130, nullptr, "ActivateOpenContextRetention"},
|
||||
{140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"},
|
||||
{150, nullptr, "AuthenticateApplicationAsync"},
|
||||
{190, nullptr, "GetUserLastOpenedApplication"},
|
||||
{191, nullptr, "ActivateOpenContextHolder"},
|
||||
{113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+
|
||||
{120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+
|
||||
{130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+
|
||||
{140, &ACC_SU::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
|
||||
{150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+
|
||||
{190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0
|
||||
{191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+
|
||||
{200, nullptr, "BeginUserRegistration"},
|
||||
{201, nullptr, "CompleteUserRegistration"},
|
||||
{202, nullptr, "CancelUserRegistration"},
|
||||
@@ -46,15 +46,15 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
|
||||
{204, nullptr, "SetUserPosition"},
|
||||
{205, &ACC_SU::GetProfileEditor, "GetProfileEditor"},
|
||||
{206, nullptr, "CompleteUserRegistrationForcibly"},
|
||||
{210, nullptr, "CreateFloatingRegistrationRequest"},
|
||||
{211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"},
|
||||
{212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"},
|
||||
{210, nullptr, "CreateFloatingRegistrationRequest"}, // 3.0.0+
|
||||
{211, nullptr, "CreateProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+
|
||||
{212, nullptr, "ResumeProcedureToRegisterUserWithNintendoAccount"}, // 8.0.0+
|
||||
{230, nullptr, "AuthenticateServiceAsync"},
|
||||
{250, nullptr, "GetBaasAccountAdministrator"},
|
||||
{290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"},
|
||||
{291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"},
|
||||
{291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"}, // 3.0.0+
|
||||
{299, nullptr, "SuspendBackgroundDaemon"},
|
||||
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
||||
{997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+
|
||||
{998, nullptr, "DebugSetUserStateClose"},
|
||||
{999, nullptr, "DebugSetUserStateOpen"},
|
||||
};
|
||||
|
||||
@@ -17,23 +17,23 @@ ACC_U0::ACC_U0(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
|
||||
{3, &ACC_U0::ListOpenUsers, "ListOpenUsers"},
|
||||
{4, &ACC_U0::GetLastOpenedUser, "GetLastOpenedUser"},
|
||||
{5, &ACC_U0::GetProfile, "GetProfile"},
|
||||
{6, nullptr, "GetProfileDigest"},
|
||||
{6, nullptr, "GetProfileDigest"}, // 3.0.0+
|
||||
{50, &ACC_U0::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
||||
{51, &ACC_U0::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
||||
{60, nullptr, "ListOpenContextStoredUsers"},
|
||||
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||
{60, nullptr, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0
|
||||
{99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+
|
||||
{100, &ACC_U0::InitializeApplicationInfo, "InitializeApplicationInfo"},
|
||||
{101, &ACC_U0::GetBaasAccountManagerForApplication, "GetBaasAccountManagerForApplication"},
|
||||
{102, nullptr, "AuthenticateApplicationAsync"},
|
||||
{103, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||
{103, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+
|
||||
{110, nullptr, "StoreSaveDataThumbnail"},
|
||||
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||
{120, nullptr, "CreateGuestLoginRequest"},
|
||||
{130, nullptr, "LoadOpenContext"},
|
||||
{131, nullptr, "ListOpenContextStoredUsers"},
|
||||
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"},
|
||||
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"},
|
||||
{150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"},
|
||||
{130, nullptr, "LoadOpenContext"}, // 5.0.0+
|
||||
{131, nullptr, "ListOpenContextStoredUsers"}, // 6.0.0+
|
||||
{140, &ACC_U0::InitializeApplicationInfoRestricted, "InitializeApplicationInfoRestricted"}, // 6.0.0+
|
||||
{141, &ACC_U0::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
|
||||
{150, &ACC_U0::IsUserAccountSwitchLocked, "IsUserAccountSwitchLocked"}, // 6.0.0+
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -17,28 +17,29 @@ ACC_U1::ACC_U1(std::shared_ptr<Module> module, std::shared_ptr<ProfileManager> p
|
||||
{3, &ACC_U1::ListOpenUsers, "ListOpenUsers"},
|
||||
{4, &ACC_U1::GetLastOpenedUser, "GetLastOpenedUser"},
|
||||
{5, &ACC_U1::GetProfile, "GetProfile"},
|
||||
{6, nullptr, "GetProfileDigest"},
|
||||
{6, nullptr, "GetProfileDigest"}, // 3.0.0+
|
||||
{50, &ACC_U1::IsUserRegistrationRequestPermitted, "IsUserRegistrationRequestPermitted"},
|
||||
{51, &ACC_U1::TrySelectUserWithoutInteraction, "TrySelectUserWithoutInteraction"},
|
||||
{60, nullptr, "ListOpenContextStoredUsers"},
|
||||
{99, nullptr, "DebugActivateOpenContextRetention"},
|
||||
{60, nullptr, "ListOpenContextStoredUsers"}, // 5.0.0 - 5.1.0
|
||||
{99, nullptr, "DebugActivateOpenContextRetention"}, // 6.0.0+
|
||||
{100, nullptr, "GetUserRegistrationNotifier"},
|
||||
{101, nullptr, "GetUserStateChangeNotifier"},
|
||||
{102, nullptr, "GetBaasAccountManagerForSystemService"},
|
||||
{103, nullptr, "GetProfileUpdateNotifier"},
|
||||
{104, nullptr, "CheckNetworkServiceAvailabilityAsync"},
|
||||
{105, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||
{106, nullptr, "GetProfileSyncNotifier"},
|
||||
{103, nullptr, "GetBaasUserAvailabilityChangeNotifier"},
|
||||
{104, nullptr, "GetProfileUpdateNotifier"},
|
||||
{105, nullptr, "CheckNetworkServiceAvailabilityAsync"}, // 4.0.0+
|
||||
{106, nullptr, "GetProfileSyncNotifier"}, // 9.0.0+
|
||||
{110, nullptr, "StoreSaveDataThumbnail"},
|
||||
{111, nullptr, "ClearSaveDataThumbnail"},
|
||||
{112, nullptr, "LoadSaveDataThumbnail"},
|
||||
{113, nullptr, "GetSaveDataThumbnailExistence"},
|
||||
{130, nullptr, "ActivateOpenContextRetention"},
|
||||
{140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"},
|
||||
{150, nullptr, "AuthenticateApplicationAsync"},
|
||||
{190, nullptr, "GetUserLastOpenedApplication"},
|
||||
{191, nullptr, "ActivateOpenContextHolder"},
|
||||
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
|
||||
{113, nullptr, "GetSaveDataThumbnailExistence"}, // 5.0.0+
|
||||
{120, nullptr, "ListOpenUsersInApplication"}, // 10.0.0+
|
||||
{130, nullptr, "ActivateOpenContextRetention"}, // 6.0.0+
|
||||
{140, &ACC_U1::ListQualifiedUsers, "ListQualifiedUsers"}, // 6.0.0+
|
||||
{150, nullptr, "AuthenticateApplicationAsync"}, // 10.0.0+
|
||||
{190, nullptr, "GetUserLastOpenedApplication"}, // 1.0.0 - 9.2.0
|
||||
{191, nullptr, "ActivateOpenContextHolder"}, // 7.0.0+
|
||||
{997, nullptr, "DebugInvalidateTokenCacheForUser"}, // 3.0.0+
|
||||
{998, nullptr, "DebugSetUserStateClose"},
|
||||
{999, nullptr, "DebugSetUserStateOpen"},
|
||||
};
|
||||
|
||||
@@ -76,7 +76,7 @@ std::unique_ptr<Input::ButtonDevice> Keyboard::Create(const Common::ParamPackage
|
||||
int key_code = params.Get("code", 0);
|
||||
std::unique_ptr<KeyButton> button = std::make_unique<KeyButton>(key_button_list);
|
||||
key_button_list->AddKeyButton(key_code, button.get());
|
||||
return std::move(button);
|
||||
return button;
|
||||
}
|
||||
|
||||
void Keyboard::PressKey(int key_code) {
|
||||
|
||||
@@ -145,7 +145,7 @@ std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackag
|
||||
// Previously created device is disconnected here. Having two motion devices for 3DS is not
|
||||
// expected.
|
||||
current_device = device_wrapper->device;
|
||||
return std::move(device_wrapper);
|
||||
return device_wrapper;
|
||||
}
|
||||
|
||||
void MotionEmu::BeginTilt(int x, int y) {
|
||||
|
||||
@@ -258,3 +258,7 @@ if (MSVC)
|
||||
else()
|
||||
target_compile_options(video_core PRIVATE -Werror=conversion -Wno-error=sign-conversion)
|
||||
endif()
|
||||
|
||||
if (APPLE)
|
||||
target_include_directories(video_core PRIVATE ../../externals/MoltenVK/include)
|
||||
endif()
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
bool is_written = false, bool use_fast_cbuf = false) {
|
||||
std::lock_guard lock{mutex};
|
||||
|
||||
const auto& memory_manager = system.GPU().MemoryManager();
|
||||
auto& memory_manager = system.GPU().MemoryManager();
|
||||
const std::optional<VAddr> cpu_addr_opt = memory_manager.GpuToCpuAddress(gpu_addr);
|
||||
if (!cpu_addr_opt) {
|
||||
return {GetEmptyBuffer(size), 0};
|
||||
@@ -59,7 +59,6 @@ public:
|
||||
constexpr std::size_t max_stream_size = 0x800;
|
||||
if (use_fast_cbuf || size < max_stream_size) {
|
||||
if (!is_written && !IsRegionWritten(cpu_addr, cpu_addr + size - 1)) {
|
||||
auto& memory_manager = system.GPU().MemoryManager();
|
||||
const bool is_granular = memory_manager.IsGranularRange(gpu_addr, size);
|
||||
if (use_fast_cbuf) {
|
||||
u8* dest;
|
||||
|
||||
@@ -54,7 +54,7 @@ void MacroJITx64Impl::Compile_ALU(Macro::Opcode opcode) {
|
||||
const bool is_a_zero = opcode.src_a == 0;
|
||||
const bool is_b_zero = opcode.src_b == 0;
|
||||
const bool valid_operation = !is_a_zero && !is_b_zero;
|
||||
const bool is_move_operation = !is_a_zero && is_b_zero;
|
||||
[[maybe_unused]] const bool is_move_operation = !is_a_zero && is_b_zero;
|
||||
const bool has_zero_register = is_a_zero || is_b_zero;
|
||||
const bool no_zero_reg_skip = opcode.alu_operation == Macro::ALUOperation::AddWithCarry ||
|
||||
opcode.alu_operation == Macro::ALUOperation::SubtractWithBorrow;
|
||||
@@ -73,7 +73,6 @@ void MacroJITx64Impl::Compile_ALU(Macro::Opcode opcode) {
|
||||
src_b = Compile_GetRegister(opcode.src_b, eax);
|
||||
}
|
||||
}
|
||||
Xbyak::Label skip_carry{};
|
||||
|
||||
bool has_emitted = false;
|
||||
|
||||
@@ -240,10 +239,10 @@ void MacroJITx64Impl::Compile_ExtractInsert(Macro::Opcode opcode) {
|
||||
}
|
||||
|
||||
void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) {
|
||||
auto dst = Compile_GetRegister(opcode.src_a, eax);
|
||||
auto src = Compile_GetRegister(opcode.src_b, RESULT);
|
||||
const auto dst = Compile_GetRegister(opcode.src_a, ecx);
|
||||
const auto src = Compile_GetRegister(opcode.src_b, RESULT);
|
||||
|
||||
shr(src, al);
|
||||
shr(src, dst.cvt8());
|
||||
if (opcode.bf_size != 0 && opcode.bf_size != 31) {
|
||||
and_(src, opcode.GetBitfieldMask());
|
||||
} else if (opcode.bf_size == 0) {
|
||||
@@ -259,8 +258,8 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftImmediate(Macro::Opcode opcode) {
|
||||
}
|
||||
|
||||
void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) {
|
||||
auto dst = Compile_GetRegister(opcode.src_a, eax);
|
||||
auto src = Compile_GetRegister(opcode.src_b, RESULT);
|
||||
const auto dst = Compile_GetRegister(opcode.src_a, ecx);
|
||||
const auto src = Compile_GetRegister(opcode.src_b, RESULT);
|
||||
|
||||
if (opcode.bf_src_bit != 0) {
|
||||
shr(src, opcode.bf_src_bit);
|
||||
@@ -269,18 +268,11 @@ void MacroJITx64Impl::Compile_ExtractShiftLeftRegister(Macro::Opcode opcode) {
|
||||
if (opcode.bf_size != 31) {
|
||||
and_(src, opcode.GetBitfieldMask());
|
||||
}
|
||||
shl(src, al);
|
||||
shl(src, dst.cvt8());
|
||||
|
||||
Compile_ProcessResult(opcode.result_operation, opcode.dst);
|
||||
}
|
||||
|
||||
static u32 Read(Engines::Maxwell3D* maxwell3d, u32 method) {
|
||||
return maxwell3d->GetRegisterValue(method);
|
||||
}
|
||||
|
||||
static void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) {
|
||||
maxwell3d->CallMethodFromMME(method_address.address, value);
|
||||
}
|
||||
|
||||
void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) {
|
||||
if (optimizer.zero_reg_skip && opcode.src_a == 0) {
|
||||
if (opcode.immediate == 0) {
|
||||
@@ -298,15 +290,27 @@ void MacroJITx64Impl::Compile_Read(Macro::Opcode opcode) {
|
||||
sub(result, opcode.immediate * -1);
|
||||
}
|
||||
}
|
||||
Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0);
|
||||
mov(Common::X64::ABI_PARAM1, qword[STATE]);
|
||||
mov(Common::X64::ABI_PARAM2, RESULT);
|
||||
Common::X64::CallFarFunction(*this, &Read);
|
||||
Common::X64::ABI_PopRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0);
|
||||
mov(RESULT, Common::X64::ABI_RETURN.cvt32());
|
||||
|
||||
// Equivalent to Engines::Maxwell3D::GetRegisterValue:
|
||||
if (optimizer.enable_asserts) {
|
||||
Xbyak::Label pass_range_check;
|
||||
cmp(RESULT, static_cast<u32>(Engines::Maxwell3D::Regs::NUM_REGS));
|
||||
jb(pass_range_check);
|
||||
int3();
|
||||
L(pass_range_check);
|
||||
}
|
||||
mov(rax, qword[STATE]);
|
||||
mov(RESULT,
|
||||
dword[rax + offsetof(Engines::Maxwell3D, regs) +
|
||||
offsetof(Engines::Maxwell3D::Regs, reg_array) + RESULT.cvt64() * sizeof(u32)]);
|
||||
|
||||
Compile_ProcessResult(opcode.result_operation, opcode.dst);
|
||||
}
|
||||
|
||||
static void Send(Engines::Maxwell3D* maxwell3d, Macro::MethodAddress method_address, u32 value) {
|
||||
maxwell3d->CallMethodFromMME(method_address.address, value);
|
||||
}
|
||||
|
||||
void Tegra::MacroJITx64Impl::Compile_Send(Xbyak::Reg32 value) {
|
||||
Common::X64::ABI_PushRegistersAndAdjustStack(*this, PersistentCallerSavedRegs(), 0);
|
||||
mov(Common::X64::ABI_PARAM1, qword[STATE]);
|
||||
@@ -438,6 +442,9 @@ void MacroJITx64Impl::Compile() {
|
||||
// one if our register isn't "dirty"
|
||||
optimizer.optimize_for_method_move = true;
|
||||
|
||||
// Enable run-time assertions in JITted code
|
||||
optimizer.enable_asserts = false;
|
||||
|
||||
// Check to see if we can skip emitting certain instructions
|
||||
Optimizer_ScanFlags();
|
||||
|
||||
@@ -546,7 +553,7 @@ Xbyak::Reg32 MacroJITx64Impl::Compile_GetRegister(u32 index, Xbyak::Reg32 dst) {
|
||||
}
|
||||
|
||||
void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u32 reg) {
|
||||
auto SetRegister = [=](u32 reg, Xbyak::Reg32 result) {
|
||||
const auto SetRegister = [this](u32 reg, const Xbyak::Reg32& result) {
|
||||
// Register 0 is supposed to always return 0. NOP is implemented as a store to the zero
|
||||
// register.
|
||||
if (reg == 0) {
|
||||
@@ -554,7 +561,7 @@ void MacroJITx64Impl::Compile_ProcessResult(Macro::ResultOperation operation, u3
|
||||
}
|
||||
mov(dword[STATE + offsetof(JITState, registers) + reg * sizeof(u32)], result);
|
||||
};
|
||||
auto SetMethodAddress = [=](Xbyak::Reg32 reg) { mov(METHOD_ADDRESS, reg); };
|
||||
const auto SetMethodAddress = [this](const Xbyak::Reg32& reg) { mov(METHOD_ADDRESS, reg); };
|
||||
|
||||
switch (operation) {
|
||||
case Macro::ResultOperation::IgnoreAndFetch:
|
||||
|
||||
@@ -76,6 +76,7 @@ private:
|
||||
bool zero_reg_skip{};
|
||||
bool skip_dummy_addimmediate{};
|
||||
bool optimize_for_method_move{};
|
||||
bool enable_asserts{};
|
||||
};
|
||||
OptimizerState optimizer{};
|
||||
|
||||
|
||||
@@ -210,10 +210,11 @@ bool MemoryManager::IsBlockContinuous(const GPUVAddr start, const std::size_t si
|
||||
return range == inner_size;
|
||||
}
|
||||
|
||||
void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::size_t size) const {
|
||||
void MemoryManager::ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer,
|
||||
const std::size_t size) const {
|
||||
std::size_t remaining_size{size};
|
||||
std::size_t page_index{src_addr >> page_bits};
|
||||
std::size_t page_offset{src_addr & page_mask};
|
||||
std::size_t page_index{gpu_src_addr >> page_bits};
|
||||
std::size_t page_offset{gpu_src_addr & page_mask};
|
||||
|
||||
auto& memory = system.Memory();
|
||||
|
||||
@@ -234,11 +235,11 @@ void MemoryManager::ReadBlock(GPUVAddr src_addr, void* dest_buffer, const std::s
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer,
|
||||
void MemoryManager::ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer,
|
||||
const std::size_t size) const {
|
||||
std::size_t remaining_size{size};
|
||||
std::size_t page_index{src_addr >> page_bits};
|
||||
std::size_t page_offset{src_addr & page_mask};
|
||||
std::size_t page_index{gpu_src_addr >> page_bits};
|
||||
std::size_t page_offset{gpu_src_addr & page_mask};
|
||||
|
||||
auto& memory = system.Memory();
|
||||
|
||||
@@ -259,10 +260,11 @@ void MemoryManager::ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const std::size_t size) {
|
||||
void MemoryManager::WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer,
|
||||
const std::size_t size) {
|
||||
std::size_t remaining_size{size};
|
||||
std::size_t page_index{dest_addr >> page_bits};
|
||||
std::size_t page_offset{dest_addr & page_mask};
|
||||
std::size_t page_index{gpu_dest_addr >> page_bits};
|
||||
std::size_t page_offset{gpu_dest_addr & page_mask};
|
||||
|
||||
auto& memory = system.Memory();
|
||||
|
||||
@@ -283,11 +285,11 @@ void MemoryManager::WriteBlock(GPUVAddr dest_addr, const void* src_buffer, const
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer,
|
||||
void MemoryManager::WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer,
|
||||
const std::size_t size) {
|
||||
std::size_t remaining_size{size};
|
||||
std::size_t page_index{dest_addr >> page_bits};
|
||||
std::size_t page_offset{dest_addr & page_mask};
|
||||
std::size_t page_index{gpu_dest_addr >> page_bits};
|
||||
std::size_t page_offset{gpu_dest_addr & page_mask};
|
||||
|
||||
auto& memory = system.Memory();
|
||||
|
||||
@@ -306,16 +308,18 @@ void MemoryManager::WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer,
|
||||
}
|
||||
}
|
||||
|
||||
void MemoryManager::CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, const std::size_t size) {
|
||||
void MemoryManager::CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr,
|
||||
const std::size_t size) {
|
||||
std::vector<u8> tmp_buffer(size);
|
||||
ReadBlock(src_addr, tmp_buffer.data(), size);
|
||||
WriteBlock(dest_addr, tmp_buffer.data(), size);
|
||||
ReadBlock(gpu_src_addr, tmp_buffer.data(), size);
|
||||
WriteBlock(gpu_dest_addr, tmp_buffer.data(), size);
|
||||
}
|
||||
|
||||
void MemoryManager::CopyBlockUnsafe(GPUVAddr dest_addr, GPUVAddr src_addr, const std::size_t size) {
|
||||
void MemoryManager::CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr,
|
||||
const std::size_t size) {
|
||||
std::vector<u8> tmp_buffer(size);
|
||||
ReadBlockUnsafe(src_addr, tmp_buffer.data(), size);
|
||||
WriteBlockUnsafe(dest_addr, tmp_buffer.data(), size);
|
||||
ReadBlockUnsafe(gpu_src_addr, tmp_buffer.data(), size);
|
||||
WriteBlockUnsafe(gpu_dest_addr, tmp_buffer.data(), size);
|
||||
}
|
||||
|
||||
bool MemoryManager::IsGranularRange(GPUVAddr gpu_addr, std::size_t size) {
|
||||
|
||||
@@ -79,9 +79,9 @@ public:
|
||||
* in the Host Memory counterpart. Note: This functions cause Host GPU Memory
|
||||
* Flushes and Invalidations, respectively to each operation.
|
||||
*/
|
||||
void ReadBlock(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const;
|
||||
void WriteBlock(GPUVAddr dest_addr, const void* src_buffer, std::size_t size);
|
||||
void CopyBlock(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size);
|
||||
void ReadBlock(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size) const;
|
||||
void WriteBlock(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size);
|
||||
void CopyBlock(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size);
|
||||
|
||||
/**
|
||||
* ReadBlockUnsafe and WriteBlockUnsafe are special versions of ReadBlock and
|
||||
@@ -93,9 +93,9 @@ public:
|
||||
* WriteBlockUnsafe instead of WriteBlock since it shouldn't invalidate the texture
|
||||
* being flushed.
|
||||
*/
|
||||
void ReadBlockUnsafe(GPUVAddr src_addr, void* dest_buffer, std::size_t size) const;
|
||||
void WriteBlockUnsafe(GPUVAddr dest_addr, const void* src_buffer, std::size_t size);
|
||||
void CopyBlockUnsafe(GPUVAddr dest_addr, GPUVAddr src_addr, std::size_t size);
|
||||
void ReadBlockUnsafe(GPUVAddr gpu_src_addr, void* dest_buffer, std::size_t size) const;
|
||||
void WriteBlockUnsafe(GPUVAddr gpu_dest_addr, const void* src_buffer, std::size_t size);
|
||||
void CopyBlockUnsafe(GPUVAddr gpu_dest_addr, GPUVAddr gpu_src_addr, std::size_t size);
|
||||
|
||||
/**
|
||||
* IsGranularRange checks if a gpu region can be simply read with a pointer
|
||||
|
||||
@@ -220,8 +220,8 @@ private:
|
||||
return cache_begin < addr_end && addr_begin < cache_end;
|
||||
};
|
||||
|
||||
const u64 page_end = addr_end >> PAGE_SHIFT;
|
||||
for (u64 page = addr_begin >> PAGE_SHIFT; page <= page_end; ++page) {
|
||||
const u64 page_end = addr_end >> PAGE_BITS;
|
||||
for (u64 page = addr_begin >> PAGE_BITS; page <= page_end; ++page) {
|
||||
const auto& it = cached_queries.find(page);
|
||||
if (it == std::end(cached_queries)) {
|
||||
continue;
|
||||
@@ -242,14 +242,14 @@ private:
|
||||
/// Registers the passed parameters as cached and returns a pointer to the stored cached query.
|
||||
CachedQuery* Register(VideoCore::QueryType type, VAddr cpu_addr, u8* host_ptr, bool timestamp) {
|
||||
rasterizer.UpdatePagesCachedCount(cpu_addr, CachedQuery::SizeInBytes(timestamp), 1);
|
||||
const u64 page = static_cast<u64>(cpu_addr) >> PAGE_SHIFT;
|
||||
const u64 page = static_cast<u64>(cpu_addr) >> PAGE_BITS;
|
||||
return &cached_queries[page].emplace_back(static_cast<QueryCache&>(*this), type, cpu_addr,
|
||||
host_ptr);
|
||||
}
|
||||
|
||||
/// Tries to a get a cached query. Returns nullptr on failure.
|
||||
CachedQuery* TryGet(VAddr addr) {
|
||||
const u64 page = static_cast<u64>(addr) >> PAGE_SHIFT;
|
||||
const u64 page = static_cast<u64>(addr) >> PAGE_BITS;
|
||||
const auto it = cached_queries.find(page);
|
||||
if (it == std::end(cached_queries)) {
|
||||
return nullptr;
|
||||
@@ -268,7 +268,7 @@ private:
|
||||
}
|
||||
|
||||
static constexpr std::uintptr_t PAGE_SIZE = 4096;
|
||||
static constexpr unsigned PAGE_SHIFT = 12;
|
||||
static constexpr unsigned PAGE_BITS = 12;
|
||||
|
||||
Core::System& system;
|
||||
VideoCore::RasterizerInterface& rasterizer;
|
||||
|
||||
@@ -281,14 +281,14 @@ private:
|
||||
|
||||
template <const std::string_view& op>
|
||||
std::string Unary(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("{}{} {}, {};", op, Modifiers(operation), temporary, Visit(operation[0]));
|
||||
return temporary;
|
||||
}
|
||||
|
||||
template <const std::string_view& op>
|
||||
std::string Binary(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("{}{} {}, {}, {};", op, Modifiers(operation), temporary, Visit(operation[0]),
|
||||
Visit(operation[1]));
|
||||
return temporary;
|
||||
@@ -296,7 +296,7 @@ private:
|
||||
|
||||
template <const std::string_view& op>
|
||||
std::string Trinary(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("{}{} {}, {}, {}, {};", op, Modifiers(operation), temporary, Visit(operation[0]),
|
||||
Visit(operation[1]), Visit(operation[2]));
|
||||
return temporary;
|
||||
@@ -304,7 +304,7 @@ private:
|
||||
|
||||
template <const std::string_view& op, bool unordered>
|
||||
std::string FloatComparison(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("TRUNC.U.CC RC.x, {};", Binary<op>(operation));
|
||||
AddLine("MOV.S {}, 0;", temporary);
|
||||
AddLine("MOV.S {} (NE.x), -1;", temporary);
|
||||
@@ -331,7 +331,7 @@ private:
|
||||
|
||||
template <const std::string_view& op, bool is_nan>
|
||||
std::string HalfComparison(Operation operation) {
|
||||
const std::string tmp1 = AllocVectorTemporary();
|
||||
std::string tmp1 = AllocVectorTemporary();
|
||||
const std::string tmp2 = AllocVectorTemporary();
|
||||
const std::string op_a = Visit(operation[0]);
|
||||
const std::string op_b = Visit(operation[1]);
|
||||
@@ -367,15 +367,14 @@ private:
|
||||
AddLine("MOV.F {}.{}, {};", value, Swizzle(i), Visit(meta.values[i]));
|
||||
}
|
||||
|
||||
const std::string result = coord;
|
||||
AddLine("ATOMIM.{}.{} {}.x, {}, {}, image[{}], {};", op, type, result, value, coord,
|
||||
AddLine("ATOMIM.{}.{} {}.x, {}, {}, image[{}], {};", op, type, coord, value, coord,
|
||||
image_id, ImageType(meta.image.type));
|
||||
return fmt::format("{}.x", result);
|
||||
return fmt::format("{}.x", coord);
|
||||
}
|
||||
|
||||
template <const std::string_view& op, const std::string_view& type>
|
||||
std::string Atomic(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
std::string address;
|
||||
std::string_view opname;
|
||||
if (const auto gmem = std::get_if<GmemNode>(&*operation[0])) {
|
||||
@@ -396,7 +395,7 @@ private:
|
||||
|
||||
template <char type>
|
||||
std::string Negate(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
if constexpr (type == 'F') {
|
||||
AddLine("MOV.F32 {}, -{};", temporary, Visit(operation[0]));
|
||||
} else {
|
||||
@@ -407,7 +406,7 @@ private:
|
||||
|
||||
template <char type>
|
||||
std::string Absolute(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("MOV.{} {}, |{}|;", type, temporary, Visit(operation[0]));
|
||||
return temporary;
|
||||
}
|
||||
@@ -1156,20 +1155,20 @@ void ARBDecompiler::VisitAST(const ASTNode& node) {
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::VisitExpression(const Expr& node) {
|
||||
const std::string result = AllocTemporary();
|
||||
if (const auto expr = std::get_if<ExprAnd>(&*node)) {
|
||||
std::string result = AllocTemporary();
|
||||
AddLine("AND.U {}, {}, {};", result, VisitExpression(expr->operand1),
|
||||
VisitExpression(expr->operand2));
|
||||
return result;
|
||||
}
|
||||
if (const auto expr = std::get_if<ExprOr>(&*node)) {
|
||||
const std::string result = AllocTemporary();
|
||||
std::string result = AllocTemporary();
|
||||
AddLine("OR.U {}, {}, {};", result, VisitExpression(expr->operand1),
|
||||
VisitExpression(expr->operand2));
|
||||
return result;
|
||||
}
|
||||
if (const auto expr = std::get_if<ExprNot>(&*node)) {
|
||||
const std::string result = AllocTemporary();
|
||||
std::string result = AllocTemporary();
|
||||
AddLine("CMP.S {}, {}, 0, -1;", result, VisitExpression(expr->operand1));
|
||||
return result;
|
||||
}
|
||||
@@ -1186,7 +1185,7 @@ std::string ARBDecompiler::VisitExpression(const Expr& node) {
|
||||
return expr->value ? "0xffffffff" : "0";
|
||||
}
|
||||
if (const auto expr = std::get_if<ExprGprEqual>(&*node)) {
|
||||
const std::string result = AllocTemporary();
|
||||
std::string result = AllocTemporary();
|
||||
AddLine("SEQ.U {}, R{}.x, {};", result, expr->gpr, expr->value);
|
||||
return result;
|
||||
}
|
||||
@@ -1231,13 +1230,13 @@ std::string ARBDecompiler::Visit(const Node& node) {
|
||||
}
|
||||
|
||||
if (const auto immediate = std::get_if<ImmediateNode>(&*node)) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("MOV.U {}, {};", temporary, immediate->GetValue());
|
||||
return temporary;
|
||||
}
|
||||
|
||||
if (const auto predicate = std::get_if<PredicateNode>(&*node)) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
switch (const auto index = predicate->GetIndex(); index) {
|
||||
case Tegra::Shader::Pred::UnusedIndex:
|
||||
AddLine("MOV.S {}, -1;", temporary);
|
||||
@@ -1333,13 +1332,13 @@ std::string ARBDecompiler::Visit(const Node& node) {
|
||||
} else {
|
||||
offset_string = Visit(offset);
|
||||
}
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("LDC.F32 {}, cbuf{}[{}];", temporary, cbuf->GetIndex(), offset_string);
|
||||
return temporary;
|
||||
}
|
||||
|
||||
if (const auto gmem = std::get_if<GmemNode>(&*node)) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("SUB.U {}, {}, {};", temporary, Visit(gmem->GetRealAddress()),
|
||||
Visit(gmem->GetBaseAddress()));
|
||||
AddLine("LDB.U32 {}, {}[{}];", temporary, GlobalMemoryName(gmem->GetDescriptor()),
|
||||
@@ -1348,14 +1347,14 @@ std::string ARBDecompiler::Visit(const Node& node) {
|
||||
}
|
||||
|
||||
if (const auto lmem = std::get_if<LmemNode>(&*node)) {
|
||||
const std::string temporary = Visit(lmem->GetAddress());
|
||||
std::string temporary = Visit(lmem->GetAddress());
|
||||
AddLine("SHR.U {}, {}, 2;", temporary, temporary);
|
||||
AddLine("MOV.U {}, lmem[{}].x;", temporary, temporary);
|
||||
return temporary;
|
||||
}
|
||||
|
||||
if (const auto smem = std::get_if<SmemNode>(&*node)) {
|
||||
const std::string temporary = Visit(smem->GetAddress());
|
||||
std::string temporary = Visit(smem->GetAddress());
|
||||
AddLine("LDS.U32 {}, shared_mem[{}];", temporary, temporary);
|
||||
return temporary;
|
||||
}
|
||||
@@ -1535,7 +1534,7 @@ std::string ARBDecompiler::Assign(Operation operation) {
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::Select(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("CMP.S {}, {}, {}, {};", temporary, Visit(operation[0]), Visit(operation[1]),
|
||||
Visit(operation[2]));
|
||||
return temporary;
|
||||
@@ -1545,12 +1544,12 @@ std::string ARBDecompiler::FClamp(Operation operation) {
|
||||
// 1.0f in hex, replace with std::bit_cast on C++20
|
||||
static constexpr u32 POSITIVE_ONE = 0x3f800000;
|
||||
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
const Node& value = operation[0];
|
||||
const Node& low = operation[1];
|
||||
const Node& high = operation[2];
|
||||
const auto imm_low = std::get_if<ImmediateNode>(&*low);
|
||||
const auto imm_high = std::get_if<ImmediateNode>(&*high);
|
||||
const auto* const imm_low = std::get_if<ImmediateNode>(&*low);
|
||||
const auto* const imm_high = std::get_if<ImmediateNode>(&*high);
|
||||
if (imm_low && imm_high && imm_low->GetValue() == 0 && imm_high->GetValue() == POSITIVE_ONE) {
|
||||
AddLine("MOV.F32.SAT {}, {};", temporary, Visit(value));
|
||||
} else {
|
||||
@@ -1574,7 +1573,7 @@ std::string ARBDecompiler::FCastHalf1(Operation operation) {
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::FSqrt(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("RSQ.F32 {}, {};", temporary, Visit(operation[0]));
|
||||
AddLine("RCP.F32 {}, {};", temporary, temporary);
|
||||
return temporary;
|
||||
@@ -1588,7 +1587,7 @@ std::string ARBDecompiler::FSwizzleAdd(Operation operation) {
|
||||
AddLine("ADD.F {}.x, {}, {};", temporary, Visit(operation[0]), Visit(operation[1]));
|
||||
return fmt::format("{}.x", temporary);
|
||||
}
|
||||
const std::string lut = AllocVectorTemporary();
|
||||
|
||||
AddLine("AND.U {}.z, {}.threadid, 3;", temporary, StageInputName(stage));
|
||||
AddLine("SHL.U {}.z, {}.z, 1;", temporary, temporary);
|
||||
AddLine("SHR.U {}.z, {}, {}.z;", temporary, Visit(operation[2]), temporary);
|
||||
@@ -1766,21 +1765,21 @@ std::string ARBDecompiler::LogicalAssign(Operation operation) {
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::LogicalPick2(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
const u32 index = std::get<ImmediateNode>(*operation[1]).GetValue();
|
||||
AddLine("MOV.U {}, {}.{};", temporary, Visit(operation[0]), Swizzle(index));
|
||||
return temporary;
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::LogicalAnd2(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
const std::string op = Visit(operation[0]);
|
||||
AddLine("AND.U {}, {}.x, {}.y;", temporary, op, op);
|
||||
return temporary;
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::FloatOrdered(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("MOVC.F32 RC.x, {};", Visit(operation[0]));
|
||||
AddLine("MOVC.F32 RC.y, {};", Visit(operation[1]));
|
||||
AddLine("MOV.S {}, -1;", temporary);
|
||||
@@ -1790,7 +1789,7 @@ std::string ARBDecompiler::FloatOrdered(Operation operation) {
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::FloatUnordered(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("MOVC.F32 RC.x, {};", Visit(operation[0]));
|
||||
AddLine("MOVC.F32 RC.y, {};", Visit(operation[1]));
|
||||
AddLine("MOV.S {}, 0;", temporary);
|
||||
@@ -1800,7 +1799,7 @@ std::string ARBDecompiler::FloatUnordered(Operation operation) {
|
||||
}
|
||||
|
||||
std::string ARBDecompiler::LogicalAddCarry(Operation operation) {
|
||||
const std::string temporary = AllocTemporary();
|
||||
std::string temporary = AllocTemporary();
|
||||
AddLine("ADDC.U RC, {}, {};", Visit(operation[0]), Visit(operation[1]));
|
||||
AddLine("MOV.S {}, 0;", temporary);
|
||||
AddLine("IF CF.x;");
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/dynamic_library.h"
|
||||
#include "common/file_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/telemetry.h"
|
||||
#include "core/core.h"
|
||||
@@ -39,6 +40,13 @@
|
||||
#include <vulkan/vulkan_win32.h>
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define VK_USE_PLATFORM_METAL_EXT
|
||||
#include <objc/message.h>
|
||||
#include "vulkan/vulkan_macos.h"
|
||||
#include "vulkan/vulkan_metal.h"
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
#include <X11/Xlib.h>
|
||||
#include <vulkan/vulkan_wayland.h>
|
||||
@@ -76,7 +84,8 @@ Common::DynamicLibrary OpenVulkanLibrary() {
|
||||
char* libvulkan_env = getenv("LIBVULKAN_PATH");
|
||||
if (!libvulkan_env || !library.Open(libvulkan_env)) {
|
||||
// Use the libvulkan.dylib from the application bundle.
|
||||
std::string filename = File::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib";
|
||||
const std::string filename =
|
||||
FileUtil::GetBundleDirectory() + "/Contents/Frameworks/libvulkan.dylib";
|
||||
library.Open(filename.c_str());
|
||||
}
|
||||
#else
|
||||
@@ -116,6 +125,11 @@ vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatc
|
||||
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
|
||||
break;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
case Core::Frontend::WindowSystemType::MacOS:
|
||||
extensions.push_back(VK_EXT_METAL_SURFACE_EXTENSION_NAME);
|
||||
break;
|
||||
#endif
|
||||
#if !defined(_WIN32) && !defined(__APPLE__)
|
||||
case Core::Frontend::WindowSystemType::X11:
|
||||
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
|
||||
@@ -135,7 +149,7 @@ vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatc
|
||||
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
}
|
||||
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
|
||||
|
||||
extensions.push_back(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME);
|
||||
const std::optional properties = vk::EnumerateInstanceExtensionProperties(dld);
|
||||
if (!properties) {
|
||||
LOG_ERROR(Render_Vulkan, "Failed to query extension properties");
|
||||
@@ -153,7 +167,7 @@ vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatc
|
||||
}
|
||||
}
|
||||
|
||||
static constexpr std::array layers_data{"VK_LAYER_LUNARG_standard_validation"};
|
||||
static constexpr std::array layers_data{"VK_LAYER_KHRONOS_validation"};
|
||||
vk::Span<const char*> layers = layers_data;
|
||||
if (!enable_layers) {
|
||||
layers = {};
|
||||
@@ -262,20 +276,56 @@ bool RendererVulkan::TryPresent(int /*timeout_ms*/) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrepareMetalWindow([[maybe_unused]] void*& render_surface) {
|
||||
#if defined(VK_USE_PLATFORM_METAL_EXT)
|
||||
// Hackish: avoids having to write Objective C++ just to create a metal layer.
|
||||
id view = reinterpret_cast<id>(render_surface);
|
||||
Class clsCAMetalLayer = objc_getClass("CAMetalLayer");
|
||||
if (!clsCAMetalLayer) {
|
||||
LOG_ERROR(Render_Vulkan, "Failed to get CAMetalLayer class.");
|
||||
return;
|
||||
}
|
||||
|
||||
// [CAMetalLayer layer]
|
||||
id layer = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(objc_getClass("CAMetalLayer"),
|
||||
sel_getUid("layer"));
|
||||
if (!layer) {
|
||||
LOG_ERROR(Render_Vulkan, "Failed to create Metal layer.");
|
||||
return;
|
||||
}
|
||||
// [view setWantsLayer:YES]
|
||||
reinterpret_cast<void (*)(id, SEL, BOOL)>(objc_msgSend)(view, sel_getUid("setWantsLayer:"),
|
||||
YES);
|
||||
// [view setLayer:layer]
|
||||
reinterpret_cast<void (*)(id, SEL, id)>(objc_msgSend)(view, sel_getUid("setLayer:"), layer);
|
||||
// NSScreen* screen = [NSScreen mainScreen]
|
||||
id screen = reinterpret_cast<id (*)(Class, SEL)>(objc_msgSend)(objc_getClass("NSScreen"),
|
||||
sel_getUid("mainScreen"));
|
||||
// CGFloat factor = [screen backingScaleFactor]
|
||||
double factor = reinterpret_cast<double (*)(id, SEL)>(objc_msgSend)(
|
||||
screen, sel_getUid("backingScaleFactor"));
|
||||
// layer.contentsScale = factor
|
||||
reinterpret_cast<void (*)(id, SEL, double)>(objc_msgSend)(
|
||||
layer, sel_getUid("setContentsScale:"), factor);
|
||||
// Store layer ptr, so MoltenVK doesn't call [NSView layer] outside main thread.
|
||||
render_surface = layer;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool RendererVulkan::Init() {
|
||||
#ifdef __APPLE__
|
||||
PrepareMetalWindow(render_window.GetRenderSurface());
|
||||
#endif
|
||||
library = OpenVulkanLibrary();
|
||||
instance = CreateInstance(library, dld, render_window.GetWindowInfo().type,
|
||||
Settings::values.renderer_debug);
|
||||
if (!instance || !CreateDebugCallback() || !CreateSurface() || !PickDevices()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Report();
|
||||
|
||||
memory_manager = std::make_unique<VKMemoryManager>(*device);
|
||||
|
||||
resource_manager = std::make_unique<VKResourceManager>(*device);
|
||||
|
||||
const auto& framebuffer = render_window.GetFramebufferLayout();
|
||||
swapchain = std::make_unique<VKSwapchain>(*surface, *device);
|
||||
swapchain->Create(framebuffer.width, framebuffer.height, false);
|
||||
@@ -327,7 +377,6 @@ bool RendererVulkan::CreateDebugCallback() {
|
||||
bool RendererVulkan::CreateSurface() {
|
||||
[[maybe_unused]] const auto& window_info = render_window.GetWindowInfo();
|
||||
VkSurfaceKHR unsafe_surface = nullptr;
|
||||
|
||||
#ifdef _WIN32
|
||||
if (window_info.type == Core::Frontend::WindowSystemType::Windows) {
|
||||
const HWND hWnd = static_cast<HWND>(window_info.render_surface);
|
||||
@@ -370,12 +419,26 @@ bool RendererVulkan::CreateSurface() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef VK_USE_PLATFORM_METAL_EXT
|
||||
if (window_info.type == Core::Frontend::WindowSystemType::MacOS) {
|
||||
VkMetalSurfaceCreateInfoEXT surface_create_info = {
|
||||
VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT, nullptr, 0,
|
||||
static_cast<const CAMetalLayer*>(window_info.render_surface)};
|
||||
const auto vkCreateMetalSurfaceEXT = reinterpret_cast<PFN_vkCreateMetalSurfaceEXT>(
|
||||
dld.vkGetInstanceProcAddr(*instance, "vkCreateMetalSurfaceEXT"));
|
||||
if (!vkCreateMetalSurfaceEXT ||
|
||||
vkCreateMetalSurfaceEXT(*instance, &surface_create_info, nullptr, &unsafe_surface) !=
|
||||
VK_SUCCESS) {
|
||||
LOG_ERROR(Render_Vulkan, "Failed to initialize Metal surface");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (!unsafe_surface) {
|
||||
LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform");
|
||||
return false;
|
||||
}
|
||||
|
||||
surface = vk::SurfaceKHR(unsafe_surface, *instance, dld);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,8 @@ struct VKScreenInfo {
|
||||
bool is_srgb{};
|
||||
};
|
||||
|
||||
void PrepareMetalWindow([[maybe_unused]] void*& render_surface);
|
||||
|
||||
class RendererVulkan final : public VideoCore::RendererBase {
|
||||
public:
|
||||
explicit RendererVulkan(Core::Frontend::EmuWindow& window, Core::System& system);
|
||||
|
||||
@@ -33,12 +33,17 @@ constexpr std::array REQUIRED_EXTENSIONS = {
|
||||
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
|
||||
VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
|
||||
VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
|
||||
VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
|
||||
VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
|
||||
VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
|
||||
VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME,
|
||||
// If device doesn't support draw_parameters there's no chance it runs anything
|
||||
VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,
|
||||
#ifndef __APPLE__
|
||||
VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
|
||||
// Subgroup ballot/vote will be supported by MoltenVK shortly
|
||||
VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME,
|
||||
VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME,
|
||||
VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME,
|
||||
#endif
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@@ -180,7 +185,11 @@ bool VKDevice::Create() {
|
||||
features.fullDrawIndexUint32 = false;
|
||||
features.imageCubeArray = false;
|
||||
features.independentBlend = true;
|
||||
#ifdef __APPLE__
|
||||
features.geometryShader = false;
|
||||
#else
|
||||
features.geometryShader = true;
|
||||
#endif
|
||||
features.tessellationShader = true;
|
||||
features.sampleRateShading = false;
|
||||
features.dualSrcBlend = false;
|
||||
@@ -495,13 +504,15 @@ bool VKDevice::IsSuitable(vk::PhysicalDevice physical, VkSurfaceKHR surface) {
|
||||
std::make_pair(features.largePoints, "largePoints"),
|
||||
std::make_pair(features.multiViewport, "multiViewport"),
|
||||
std::make_pair(features.depthBiasClamp, "depthBiasClamp"),
|
||||
std::make_pair(features.geometryShader, "geometryShader"),
|
||||
std::make_pair(features.tessellationShader, "tessellationShader"),
|
||||
std::make_pair(features.occlusionQueryPrecise, "occlusionQueryPrecise"),
|
||||
std::make_pair(features.fragmentStoresAndAtomics, "fragmentStoresAndAtomics"),
|
||||
std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"),
|
||||
std::make_pair(features.shaderStorageImageWriteWithoutFormat,
|
||||
"shaderStorageImageWriteWithoutFormat"),
|
||||
#ifndef __APPLE__
|
||||
std::make_pair(features.geometryShader, "geometryShader"),
|
||||
#endif
|
||||
};
|
||||
for (const auto& [supported, name] : feature_report) {
|
||||
if (supported) {
|
||||
|
||||
@@ -595,8 +595,11 @@ void RasterizerVulkan::WaitForIdle() {
|
||||
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
#ifndef __APPLE__
|
||||
flags = flags | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT;
|
||||
#endif
|
||||
if (device.IsExtTransformFeedbackSupported()) {
|
||||
flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
|
||||
}
|
||||
@@ -870,7 +873,7 @@ void RasterizerVulkan::BeginTransformFeedback() {
|
||||
UNIMPLEMENTED_IF(binding.buffer_offset != 0);
|
||||
|
||||
const GPUVAddr gpu_addr = binding.Address();
|
||||
const std::size_t size = binding.buffer_size;
|
||||
const auto size = static_cast<VkDeviceSize>(binding.buffer_size);
|
||||
const auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true);
|
||||
|
||||
scheduler.Record([buffer = buffer, offset = offset, size](vk::CommandBuffer cmdbuf) {
|
||||
@@ -1154,7 +1157,7 @@ void RasterizerVulkan::SetupTexture(const Tegra::Texture::FullTextureInfo& textu
|
||||
const auto sampler = sampler_cache.GetSampler(texture.tsc);
|
||||
update_descriptor_queue.AddSampledImage(sampler, image_view);
|
||||
|
||||
const auto image_layout = update_descriptor_queue.GetLastImageLayout();
|
||||
VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout();
|
||||
*image_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
sampled_views.push_back(ImageView{std::move(view), image_layout});
|
||||
}
|
||||
@@ -1180,7 +1183,7 @@ void RasterizerVulkan::SetupImage(const Tegra::Texture::TICEntry& tic, const Ima
|
||||
view->GetImageView(tic.x_source, tic.y_source, tic.z_source, tic.w_source);
|
||||
update_descriptor_queue.AddImage(image_view);
|
||||
|
||||
const auto image_layout = update_descriptor_queue.GetLastImageLayout();
|
||||
VkImageLayout* const image_layout = update_descriptor_queue.LastImageLayout();
|
||||
*image_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
image_views.push_back(ImageView{std::move(view), image_layout});
|
||||
}
|
||||
|
||||
@@ -276,14 +276,19 @@ class SPIRVDecompiler final : public Sirit::Module {
|
||||
public:
|
||||
explicit SPIRVDecompiler(const VKDevice& device, const ShaderIR& ir, ShaderType stage,
|
||||
const Registry& registry, const Specialization& specialization)
|
||||
: Module(0x00010300), device{device}, ir{ir}, stage{stage}, header{ir.GetHeader()},
|
||||
:
|
||||
#ifdef __APPLE__
|
||||
Module(0x00010000),
|
||||
#else
|
||||
Module(0x00010300),
|
||||
#endif
|
||||
device{device}, ir{ir}, stage{stage}, header{ir.GetHeader()},
|
||||
registry{registry}, specialization{specialization} {
|
||||
if (stage != ShaderType::Compute) {
|
||||
transform_feedback = BuildTransformFeedback(registry.GetGraphicsInfo());
|
||||
}
|
||||
|
||||
AddCapability(spv::Capability::Shader);
|
||||
AddCapability(spv::Capability::UniformAndStorageBuffer16BitAccess);
|
||||
AddCapability(spv::Capability::ImageQuery);
|
||||
AddCapability(spv::Capability::Image1D);
|
||||
AddCapability(spv::Capability::ImageBuffer);
|
||||
@@ -291,13 +296,19 @@ public:
|
||||
AddCapability(spv::Capability::SampledBuffer);
|
||||
AddCapability(spv::Capability::StorageImageWriteWithoutFormat);
|
||||
AddCapability(spv::Capability::DrawParameters);
|
||||
AddCapability(spv::Capability::UniformAndStorageBuffer16BitAccess);
|
||||
#ifndef __APPLE__
|
||||
// These can be added back when MoltenVK finally supports vk 1.1
|
||||
AddCapability(spv::Capability::SubgroupBallotKHR);
|
||||
AddCapability(spv::Capability::SubgroupVoteKHR);
|
||||
AddExtension("SPV_KHR_shader_ballot");
|
||||
AddExtension("SPV_KHR_subgroup_vote");
|
||||
AddExtension("SPV_KHR_storage_buffer_storage_class");
|
||||
#endif
|
||||
// Uniform 16bit Storage should only be added if version < 1.1
|
||||
AddExtension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME);
|
||||
AddExtension(VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME);
|
||||
AddExtension(VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME);
|
||||
AddExtension("SPV_KHR_variable_pointers");
|
||||
AddExtension("SPV_KHR_shader_draw_parameters");
|
||||
|
||||
if (!transform_feedback.empty()) {
|
||||
if (device.IsExtTransformFeedbackSupported()) {
|
||||
@@ -514,6 +525,8 @@ private:
|
||||
}
|
||||
|
||||
void DeclareCommon() {
|
||||
#ifndef __APPLE__
|
||||
//subgrouplocalinvocationId requires VK_EXT_shader_subgroup_ballot - isn't in metal yet
|
||||
thread_id =
|
||||
DeclareInputBuiltIn(spv::BuiltIn::SubgroupLocalInvocationId, t_in_uint, "thread_id");
|
||||
thread_masks[0] =
|
||||
@@ -526,6 +539,7 @@ private:
|
||||
DeclareInputBuiltIn(spv::BuiltIn::SubgroupLeMask, t_in_uint4, "thread_le_mask");
|
||||
thread_masks[4] =
|
||||
DeclareInputBuiltIn(spv::BuiltIn::SubgroupLtMask, t_in_uint4, "thread_lt_mask");
|
||||
#endif
|
||||
}
|
||||
|
||||
void DeclareVertex() {
|
||||
@@ -631,7 +645,11 @@ private:
|
||||
|
||||
void DeclareRegisters() {
|
||||
for (const u32 gpr : ir.GetRegisters()) {
|
||||
#ifdef __APPLE__
|
||||
const Id id = OpVariable(t_prv_float, spv::StorageClass::Private);
|
||||
#else
|
||||
const Id id = OpVariable(t_prv_float, spv::StorageClass::Private, v_float_zero);
|
||||
#endif
|
||||
Name(id, fmt::format("gpr_{}", gpr));
|
||||
registers.emplace(gpr, AddGlobalVariable(id));
|
||||
}
|
||||
@@ -640,7 +658,11 @@ private:
|
||||
void DeclareCustomVariables() {
|
||||
const u32 num_custom_variables = ir.GetNumCustomVariables();
|
||||
for (u32 i = 0; i < num_custom_variables; ++i) {
|
||||
#ifdef __APPLE__
|
||||
const Id id = OpVariable(t_prv_float, spv::StorageClass::Private);
|
||||
#else
|
||||
const Id id = OpVariable(t_prv_float, spv::StorageClass::Private, v_float_zero);
|
||||
#endif
|
||||
Name(id, fmt::format("custom_var_{}", i));
|
||||
custom_variables.emplace(i, AddGlobalVariable(id));
|
||||
}
|
||||
@@ -648,7 +670,11 @@ private:
|
||||
|
||||
void DeclarePredicates() {
|
||||
for (const auto pred : ir.GetPredicates()) {
|
||||
#ifdef __APPLE__
|
||||
const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private);
|
||||
#else
|
||||
const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
|
||||
#endif
|
||||
Name(id, fmt::format("pred_{}", static_cast<u32>(pred)));
|
||||
predicates.emplace(pred, AddGlobalVariable(id));
|
||||
}
|
||||
@@ -656,7 +682,11 @@ private:
|
||||
|
||||
void DeclareFlowVariables() {
|
||||
for (u32 i = 0; i < ir.GetASTNumVariables(); i++) {
|
||||
#ifdef __APPLE__
|
||||
const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private);
|
||||
#else
|
||||
const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
|
||||
#endif
|
||||
Name(id, fmt::format("flow_var_{}", static_cast<u32>(i)));
|
||||
flow_variables.emplace(i, AddGlobalVariable(id));
|
||||
}
|
||||
@@ -703,7 +733,11 @@ private:
|
||||
constexpr std::array names = {"zero", "sign", "carry", "overflow"};
|
||||
for (std::size_t flag = 0; flag < INTERNAL_FLAGS_COUNT; ++flag) {
|
||||
const auto flag_code = static_cast<InternalFlag>(flag);
|
||||
#ifdef __APPLE__
|
||||
const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private);
|
||||
#else
|
||||
const Id id = OpVariable(t_prv_bool, spv::StorageClass::Private, v_false);
|
||||
#endif
|
||||
internal_flags[flag] = AddGlobalVariable(Name(id, names[flag]));
|
||||
}
|
||||
}
|
||||
@@ -1327,10 +1361,11 @@ private:
|
||||
}
|
||||
|
||||
if (const auto comment = std::get_if<CommentNode>(&*node)) {
|
||||
#ifndef __APPLE__ // This doesn't work at all on moltenVK
|
||||
Name(OpUndef(t_void), comment->GetText());
|
||||
#endif
|
||||
return {};
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -24,35 +24,25 @@ void VKUpdateDescriptorQueue::TickFrame() {
|
||||
}
|
||||
|
||||
void VKUpdateDescriptorQueue::Acquire() {
|
||||
entries.clear();
|
||||
}
|
||||
// Minimum number of entries required.
|
||||
// This is the maximum number of entries a single draw call migth use.
|
||||
static constexpr std::size_t MIN_ENTRIES = 0x400;
|
||||
|
||||
void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template,
|
||||
VkDescriptorSet set) {
|
||||
if (payload.size() + entries.size() >= payload.max_size()) {
|
||||
if (payload.size() + MIN_ENTRIES >= payload.max_size()) {
|
||||
LOG_WARNING(Render_Vulkan, "Payload overflow, waiting for worker thread");
|
||||
scheduler.WaitWorker();
|
||||
payload.clear();
|
||||
}
|
||||
upload_start = &*payload.end();
|
||||
}
|
||||
|
||||
// TODO(Rodrigo): Rework to write the payload directly
|
||||
const auto payload_start = payload.data() + payload.size();
|
||||
for (const auto& entry : entries) {
|
||||
if (const auto image = std::get_if<VkDescriptorImageInfo>(&entry)) {
|
||||
payload.push_back(*image);
|
||||
} else if (const auto buffer = std::get_if<VkDescriptorBufferInfo>(&entry)) {
|
||||
payload.push_back(*buffer);
|
||||
} else if (const auto texel = std::get_if<VkBufferView>(&entry)) {
|
||||
payload.push_back(*texel);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
scheduler.Record(
|
||||
[payload_start, set, update_template, logical = &device.GetLogical()](vk::CommandBuffer) {
|
||||
logical->UpdateDescriptorSet(set, update_template, payload_start);
|
||||
});
|
||||
void VKUpdateDescriptorQueue::Send(VkDescriptorUpdateTemplateKHR update_template,
|
||||
VkDescriptorSet set) {
|
||||
const void* const data = upload_start;
|
||||
const vk::Device* const logical = &device.GetLogical();
|
||||
scheduler.Record([data, logical, set, update_template](vk::CommandBuffer) {
|
||||
logical->UpdateDescriptorSet(set, update_template, data);
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Vulkan
|
||||
|
||||
@@ -15,17 +15,13 @@ namespace Vulkan {
|
||||
class VKDevice;
|
||||
class VKScheduler;
|
||||
|
||||
class DescriptorUpdateEntry {
|
||||
public:
|
||||
explicit DescriptorUpdateEntry() {}
|
||||
struct DescriptorUpdateEntry {
|
||||
DescriptorUpdateEntry(VkDescriptorImageInfo image_) : image{image_} {}
|
||||
|
||||
DescriptorUpdateEntry(VkDescriptorImageInfo image) : image{image} {}
|
||||
DescriptorUpdateEntry(VkDescriptorBufferInfo buffer_) : buffer{buffer_} {}
|
||||
|
||||
DescriptorUpdateEntry(VkDescriptorBufferInfo buffer) : buffer{buffer} {}
|
||||
DescriptorUpdateEntry(VkBufferView texel_buffer_) : texel_buffer{texel_buffer_} {}
|
||||
|
||||
DescriptorUpdateEntry(VkBufferView texel_buffer) : texel_buffer{texel_buffer} {}
|
||||
|
||||
private:
|
||||
union {
|
||||
VkDescriptorImageInfo image;
|
||||
VkDescriptorBufferInfo buffer;
|
||||
@@ -45,32 +41,34 @@ public:
|
||||
void Send(VkDescriptorUpdateTemplateKHR update_template, VkDescriptorSet set);
|
||||
|
||||
void AddSampledImage(VkSampler sampler, VkImageView image_view) {
|
||||
entries.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}});
|
||||
payload.emplace_back(VkDescriptorImageInfo{sampler, image_view, {}});
|
||||
}
|
||||
|
||||
void AddImage(VkImageView image_view) {
|
||||
entries.emplace_back(VkDescriptorImageInfo{{}, image_view, {}});
|
||||
payload.emplace_back(VkDescriptorImageInfo{{}, image_view, {}});
|
||||
}
|
||||
|
||||
void AddBuffer(VkBuffer buffer, u64 offset, std::size_t size) {
|
||||
entries.emplace_back(VkDescriptorBufferInfo{buffer, offset, size});
|
||||
payload.emplace_back(VkDescriptorBufferInfo{buffer, offset, size});
|
||||
}
|
||||
|
||||
void AddTexelBuffer(VkBufferView texel_buffer) {
|
||||
entries.emplace_back(texel_buffer);
|
||||
payload.emplace_back(texel_buffer);
|
||||
}
|
||||
|
||||
VkImageLayout* GetLastImageLayout() {
|
||||
return &std::get<VkDescriptorImageInfo>(entries.back()).imageLayout;
|
||||
VkImageLayout* LastImageLayout() {
|
||||
return &payload.back().image.imageLayout;
|
||||
}
|
||||
|
||||
const VkImageLayout* LastImageLayout() const {
|
||||
return &payload.back().image.imageLayout;
|
||||
}
|
||||
|
||||
private:
|
||||
using Variant = std::variant<VkDescriptorImageInfo, VkDescriptorBufferInfo, VkBufferView>;
|
||||
|
||||
const VKDevice& device;
|
||||
VKScheduler& scheduler;
|
||||
|
||||
boost::container::static_vector<Variant, 0x400> entries;
|
||||
const DescriptorUpdateEntry* upload_start = nullptr;
|
||||
boost::container::static_vector<DescriptorUpdateEntry, 0x10000> payload;
|
||||
};
|
||||
|
||||
|
||||
@@ -373,7 +373,11 @@ Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions
|
||||
application_info.applicationVersion = VK_MAKE_VERSION(0, 1, 0);
|
||||
application_info.pEngineName = "yuzu Emulator";
|
||||
application_info.engineVersion = VK_MAKE_VERSION(0, 1, 0);
|
||||
#ifdef __APPLE__
|
||||
application_info.apiVersion = VK_API_VERSION_1_0;
|
||||
#else
|
||||
application_info.apiVersion = VK_API_VERSION_1_1;
|
||||
#endif
|
||||
|
||||
VkInstanceCreateInfo ci;
|
||||
ci.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
@@ -725,8 +729,7 @@ bool PhysicalDevice::GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR s
|
||||
return supported == VK_TRUE;
|
||||
}
|
||||
|
||||
VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const
|
||||
noexcept {
|
||||
VkSurfaceCapabilitiesKHR PhysicalDevice::GetSurfaceCapabilitiesKHR(VkSurfaceKHR surface) const {
|
||||
VkSurfaceCapabilitiesKHR capabilities;
|
||||
Check(dld->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physical_device, surface, &capabilities));
|
||||
return capabilities;
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
#define VK_NO_PROTOTYPES
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <MoltenVK/vk_mvk_moltenvk.h>
|
||||
#endif
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Vulkan::vk {
|
||||
@@ -779,7 +783,7 @@ public:
|
||||
|
||||
bool GetSurfaceSupportKHR(u32 queue_family_index, VkSurfaceKHR) const;
|
||||
|
||||
VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const noexcept;
|
||||
VkSurfaceCapabilitiesKHR GetSurfaceCapabilitiesKHR(VkSurfaceKHR) const;
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> GetSurfaceFormatsKHR(VkSurfaceKHR) const;
|
||||
|
||||
|
||||
@@ -66,12 +66,12 @@ ProgramCode GetShaderCode(Tegra::MemoryManager& memory_manager, GPUVAddr gpu_add
|
||||
|
||||
u64 GetUniqueIdentifier(Tegra::Engines::ShaderType shader_type, bool is_a, const ProgramCode& code,
|
||||
const ProgramCode& code_b) {
|
||||
u64 unique_identifier = boost::hash_value(code);
|
||||
size_t unique_identifier = boost::hash_value(code);
|
||||
if (is_a) {
|
||||
// VertexA programs include two programs
|
||||
boost::hash_combine(unique_identifier, boost::hash_value(code_b));
|
||||
}
|
||||
return unique_identifier;
|
||||
return static_cast<u64>(unique_identifier);
|
||||
}
|
||||
|
||||
} // namespace VideoCommon::Shader
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace VideoCommon {
|
||||
|
||||
template <class T>
|
||||
class ShaderCache {
|
||||
static constexpr u64 PAGE_SHIFT = 14;
|
||||
static constexpr u64 PAGE_BITS = 14;
|
||||
|
||||
struct Entry {
|
||||
VAddr addr_start;
|
||||
@@ -87,8 +87,8 @@ protected:
|
||||
const VAddr addr_end = addr + size;
|
||||
Entry* const entry = NewEntry(addr, addr_end, data.get());
|
||||
|
||||
const u64 page_end = addr_end >> PAGE_SHIFT;
|
||||
for (u64 page = addr >> PAGE_SHIFT; page <= page_end; ++page) {
|
||||
const u64 page_end = addr_end >> PAGE_BITS;
|
||||
for (u64 page = addr >> PAGE_BITS; page <= page_end; ++page) {
|
||||
invalidation_cache[page].push_back(entry);
|
||||
}
|
||||
|
||||
@@ -108,8 +108,8 @@ private:
|
||||
/// @pre invalidation_mutex is locked
|
||||
void InvalidatePagesInRegion(VAddr addr, std::size_t size) {
|
||||
const VAddr addr_end = addr + size;
|
||||
const u64 page_end = addr_end >> PAGE_SHIFT;
|
||||
for (u64 page = addr >> PAGE_SHIFT; page <= page_end; ++page) {
|
||||
const u64 page_end = addr_end >> PAGE_BITS;
|
||||
for (u64 page = addr >> PAGE_BITS; page <= page_end; ++page) {
|
||||
const auto it = invalidation_cache.find(page);
|
||||
if (it == invalidation_cache.end()) {
|
||||
continue;
|
||||
|
||||
@@ -208,7 +208,55 @@ if (MSVC)
|
||||
copy_yuzu_unicorn_deps(yuzu)
|
||||
endif()
|
||||
|
||||
if (NOT APPLE)
|
||||
target_compile_definitions(yuzu PRIVATE HAS_OPENGL)
|
||||
endif()
|
||||
|
||||
if (ENABLE_VULKAN)
|
||||
target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include)
|
||||
target_compile_definitions(yuzu PRIVATE HAS_VULKAN)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
target_include_directories(yuzu PRIVATE ../../externals/MoltenVK/include)
|
||||
|
||||
#include(BundleUtilities)
|
||||
set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/yuzu.app)
|
||||
|
||||
# Ask for an application bundle.
|
||||
set_target_properties(yuzu PROPERTIES
|
||||
MACOSX_BUNDLE true
|
||||
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist
|
||||
)
|
||||
|
||||
# Copy Qt plugins into the bundle
|
||||
get_target_property(qtcocoa_location Qt5::QCocoaIntegrationPlugin LOCATION)
|
||||
target_sources(yuzu PRIVATE "${qtcocoa_location}")
|
||||
set_source_files_properties("${qtcocoa_location}" PROPERTIES MACOSX_PACKAGE_LOCATION MacOS/platforms)
|
||||
|
||||
get_target_property(qtmacstyle_location Qt5::QMacStylePlugin LOCATION)
|
||||
target_sources(yuzu PRIVATE "${qtmacstyle_location}")
|
||||
set_source_files_properties("${qtmacstyle_location}" PROPERTIES MACOSX_PACKAGE_LOCATION MacOS/styles)
|
||||
|
||||
# Copy MoltenVK into the bundle
|
||||
target_sources(yuzu PRIVATE "${CMAKE_SOURCE_DIR}/externals/MoltenVK/lib/libMoltenVK.dylib")
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/externals/MoltenVK/lib/libMoltenVK.dylib" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks)
|
||||
target_sources(yuzu PRIVATE "${CMAKE_SOURCE_DIR}/externals/MoltenVK/lib/libvulkan.dylib")
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/externals/MoltenVK/lib/libvulkan.dylib" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks)
|
||||
|
||||
# Copy validation layers as well
|
||||
target_sources(yuzu PRIVATE "${CMAKE_SOURCE_DIR}/externals/MoltenVK/lib/libVkLayer_khronos_validation.dylib")
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/externals/MoltenVK/lib/libVkLayer_khronos_validation.dylib" PROPERTIES MACOSX_PACKAGE_LOCATION Frameworks)
|
||||
target_sources(yuzu PRIVATE "${CMAKE_SOURCE_DIR}/externals/MoltenVK/Resources/vulkan/icd.d/MoltenVK_icd.json")
|
||||
set_source_files_properties("${CMAKE_SOURCE_DIR}/externals/MoltenVK/Resources/vulkan/icd.d/MoltenVK_icd.json" PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/vulkan/icd.d")
|
||||
|
||||
|
||||
# Update library references to make the bundle portable
|
||||
include(PostprocessBundle)
|
||||
#postprocess_bundle(yuzu)
|
||||
# Fix rpath
|
||||
add_custom_command(TARGET yuzu
|
||||
POST_BUILD COMMAND
|
||||
${CMAKE_INSTALL_NAME_TOOL} -add_rpath "@executable_path/../Frameworks/"
|
||||
$<TARGET_FILE:yuzu>)
|
||||
endif()
|
||||
|
||||
@@ -8,13 +8,16 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QKeyEvent>
|
||||
#include <QMessageBox>
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLContext>
|
||||
#include <QPainter>
|
||||
#include <QScreen>
|
||||
#include <QStringList>
|
||||
#include <QWindow>
|
||||
|
||||
#ifdef HAS_OPENGL
|
||||
#include <QOffscreenSurface>
|
||||
#include <QOpenGLContext>
|
||||
#endif
|
||||
|
||||
#if !defined(WIN32) && HAS_VULKAN
|
||||
#include <qpa/qplatformnativeinterface.h>
|
||||
#endif
|
||||
@@ -98,6 +101,7 @@ void EmuThread::run() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_OPENGL
|
||||
class OpenGLSharedContext : public Core::Frontend::GraphicsContext {
|
||||
public:
|
||||
/// Create the original context that should be shared from
|
||||
@@ -183,6 +187,7 @@ private:
|
||||
std::unique_ptr<QOffscreenSurface> offscreen_surface{};
|
||||
QSurface* surface;
|
||||
};
|
||||
#endif
|
||||
|
||||
class DummyContext : public Core::Frontend::GraphicsContext {};
|
||||
|
||||
@@ -256,6 +261,8 @@ static Core::Frontend::WindowSystemType GetWindowSystemType() {
|
||||
return Core::Frontend::WindowSystemType::X11;
|
||||
else if (platform_name == QStringLiteral("wayland"))
|
||||
return Core::Frontend::WindowSystemType::Wayland;
|
||||
else if (platform_name == QStringLiteral("cocoa"))
|
||||
return Core::Frontend::WindowSystemType::MacOS;
|
||||
|
||||
LOG_CRITICAL(Frontend, "Unknown Qt platform!");
|
||||
return Core::Frontend::WindowSystemType::Windows;
|
||||
@@ -473,6 +480,7 @@ void GRenderWindow::resizeEvent(QResizeEvent* event) {
|
||||
}
|
||||
|
||||
std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedContext() const {
|
||||
#ifdef HAS_OPENGL
|
||||
if (Settings::values.renderer_backend == Settings::RendererBackend::OpenGL) {
|
||||
auto c = static_cast<OpenGLSharedContext*>(main_context.get());
|
||||
// Bind the shared contexts to the main surface in case the backend wants to take over
|
||||
@@ -480,6 +488,7 @@ std::unique_ptr<Core::Frontend::GraphicsContext> GRenderWindow::CreateSharedCont
|
||||
return std::make_unique<OpenGLSharedContext>(c->GetShareContext(),
|
||||
child_widget->windowHandle());
|
||||
}
|
||||
#endif
|
||||
return std::make_unique<DummyContext>();
|
||||
}
|
||||
|
||||
@@ -560,6 +569,7 @@ void GRenderWindow::OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal
|
||||
}
|
||||
|
||||
bool GRenderWindow::InitializeOpenGL() {
|
||||
#ifdef HAS_OPENGL
|
||||
// TODO: One of these flags might be interesting: WA_OpaquePaintEvent, WA_NoBackground,
|
||||
// WA_DontShowOnScreen, WA_DeleteOnClose
|
||||
auto child = new OpenGLRenderWidget(this);
|
||||
@@ -571,6 +581,11 @@ bool GRenderWindow::InitializeOpenGL() {
|
||||
std::make_unique<OpenGLSharedContext>(context->GetShareContext(), child->windowHandle()));
|
||||
|
||||
return true;
|
||||
#else
|
||||
QMessageBox::warning(this, tr("OpenGL not available!"),
|
||||
tr("yuzu has not been compiled with OpenGL support."));
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool GRenderWindow::InitializeVulkan() {
|
||||
|
||||
@@ -68,6 +68,7 @@ void ConfigureService::SetConfiguration() {
|
||||
}
|
||||
|
||||
std::pair<QString, QString> ConfigureService::BCATDownloadEvents() {
|
||||
#ifdef YUZU_ENABLE_BOXCAT
|
||||
std::optional<std::string> global;
|
||||
std::map<std::string, Service::BCAT::EventStatus> map;
|
||||
const auto res = Service::BCAT::Boxcat::GetStatus(global, map);
|
||||
@@ -105,7 +106,10 @@ std::pair<QString, QString> ConfigureService::BCATDownloadEvents() {
|
||||
.arg(QString::fromStdString(key))
|
||||
.arg(FormatEventStatusString(value));
|
||||
}
|
||||
return {QStringLiteral("Current Boxcat Events"), std::move(out)};
|
||||
return {tr("Current Boxcat Events"), std::move(out)};
|
||||
#else
|
||||
return {tr("Current Boxcat Events"), tr("There are currently no events on boxcat.")};
|
||||
#endif
|
||||
}
|
||||
|
||||
void ConfigureService::OnBCATImplChanged() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <thread>
|
||||
#ifdef __APPLE__
|
||||
#include <unistd.h> // for chdir
|
||||
#include <stdlib.h> // for setenv
|
||||
#endif
|
||||
|
||||
// VFS includes must be before glad as they will conflict with Windows file api, which uses defines.
|
||||
@@ -2442,6 +2443,9 @@ int main(int argc, char* argv[]) {
|
||||
QCoreApplication::setApplicationName(QStringLiteral("yuzu"));
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Set MoltenVK Environment Variable. Done before anything else so before graphics backend init
|
||||
// This avoids a nightmare of calling vk_mvk_moltenvk to set config settings
|
||||
setenv("MVK_CONFIG_FULL_IMAGE_VIEW_SWIZZLE", "1", 1);
|
||||
// If you start a bundle (binary) on OSX without the Terminal, the working directory is "/".
|
||||
// But since we require the working directory to be the executable path for the location of the
|
||||
// user folder in the Qt Frontend, we need to cd into that working directory
|
||||
|
||||
+1
-1
@@ -16,4 +16,4 @@ IDI_ICON1 ICON "../../dist/yuzu.ico"
|
||||
// RT_MANIFEST
|
||||
//
|
||||
|
||||
1 RT_MANIFEST "../../dist/yuzu.manifest"
|
||||
0 RT_MANIFEST "../../dist/yuzu.manifest"
|
||||
|
||||
@@ -43,3 +43,7 @@ if (MSVC)
|
||||
copy_yuzu_SDL_deps(yuzu-cmd)
|
||||
copy_yuzu_unicorn_deps(yuzu-cmd)
|
||||
endif()
|
||||
|
||||
if (APPLE AND ENABLE_VULKAN)
|
||||
target_include_directories(yuzu-cmd PRIVATE ../../externals/MoltenVK/include)
|
||||
endif()
|
||||
|
||||
@@ -14,4 +14,4 @@ YUZU_ICON ICON "../../dist/yuzu.ico"
|
||||
// RT_MANIFEST
|
||||
//
|
||||
|
||||
1 RT_MANIFEST "../../dist/yuzu.manifest"
|
||||
0 RT_MANIFEST "../../dist/yuzu.manifest"
|
||||
|
||||
@@ -14,4 +14,4 @@ YUZU_ICON ICON "../../dist/yuzu.ico"
|
||||
// RT_MANIFEST
|
||||
//
|
||||
|
||||
1 RT_MANIFEST "../../dist/yuzu.manifest"
|
||||
0 RT_MANIFEST "../../dist/yuzu.manifest"
|
||||
|
||||
Reference in New Issue
Block a user