[macOS, compat] Allow games to boot in MacOS #372
9 changed files with 82 additions and 26 deletions
|
@ -12,7 +12,7 @@
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include "common/dynamic_library.h"
|
#include "common/dynamic_library.h"
|
||||||
|
|
||||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv
|
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
#ifndef _GNU_SOURCE
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
@ -20,10 +20,18 @@
|
||||||
#include <boost/icl/interval_set.hpp>
|
#include <boost/icl/interval_set.hpp>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/random.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
|
|
||||||
|
#if defined(__linux__)
|
||||||
|
#include <sys/random.h>
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/random.h>
|
||||||
|
#include <mach/vm_map.h>
|
||||||
|
#include <mach/mach.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
// FreeBSD
|
// FreeBSD
|
||||||
#ifndef MAP_NORESERVE
|
#ifndef MAP_NORESERVE
|
||||||
#define MAP_NORESERVE 0
|
#define MAP_NORESERVE 0
|
||||||
|
@ -32,8 +40,12 @@
|
||||||
#ifndef MAP_ALIGNED_SUPER
|
#ifndef MAP_ALIGNED_SUPER
|
||||||
#define MAP_ALIGNED_SUPER 0
|
#define MAP_ALIGNED_SUPER 0
|
||||||
#endif
|
#endif
|
||||||
|
// macOS
|
||||||
|
#ifndef MAP_ANONYMOUS
|
||||||
|
#define MAP_ANONYMOUS MAP_ANON
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // ^^^ Linux ^^^
|
#endif // ^^^ POSIX ^^^
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <random>
|
#include <random>
|
||||||
|
@ -372,7 +384,7 @@ private:
|
||||||
std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset
|
std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset
|
||||||
};
|
};
|
||||||
|
|
||||||
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) // ^^^ Windows ^^^ vvv Linux vvv
|
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__) || defined(__APPLE__) // ^^^ Windows ^^^ vvv POSIX vvv
|
||||||
|
|
||||||
#ifdef ARCHITECTURE_arm64
|
#ifdef ARCHITECTURE_arm64
|
||||||
|
|
||||||
|
@ -489,6 +501,13 @@ public:
|
||||||
#elif defined(__FreeBSD__) && __FreeBSD__ < 13
|
#elif defined(__FreeBSD__) && __FreeBSD__ < 13
|
||||||
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
|
// XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30
|
||||||
fd = shm_open(SHM_ANON, O_RDWR, 0600);
|
fd = shm_open(SHM_ANON, O_RDWR, 0600);
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
// macOS doesn't have memfd_create, use anonymous temporary file
|
||||||
|
char template_path[] = "/tmp/eden_mem_XXXXXX";
|
||||||
|
fd = mkstemp(template_path);
|
||||||
|
if (fd >= 0) {
|
||||||
|
unlink(template_path);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
fd = memfd_create("HostMemory", 0);
|
fd = memfd_create("HostMemory", 0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -645,7 +664,7 @@ private:
|
||||||
FreeRegionManager free_manager{};
|
FreeRegionManager free_manager{};
|
||||||
};
|
};
|
||||||
|
|
||||||
#else // ^^^ Linux ^^^ vvv Generic vvv
|
#else // ^^^ POSIX ^^^ vvv Generic vvv
|
||||||
|
|
||||||
class HostMemory::Impl {
|
class HostMemory::Impl {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -551,6 +551,8 @@ struct Values {
|
||||||
3,
|
3,
|
||||||
#elif defined (ANDROID)
|
#elif defined (ANDROID)
|
||||||
0,
|
0,
|
||||||
|
#elif defined (__APPLE__)
|
||||||
|
0,
|
||||||
#else
|
#else
|
||||||
2,
|
2,
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -102,13 +102,16 @@ constexpr VkPipelineVertexInputStateCreateInfo PIPELINE_VERTEX_INPUT_STATE_CREAT
|
||||||
.vertexAttributeDescriptionCount = 0,
|
.vertexAttributeDescriptionCount = 0,
|
||||||
.pVertexAttributeDescriptions = nullptr,
|
.pVertexAttributeDescriptions = nullptr,
|
||||||
};
|
};
|
||||||
constexpr VkPipelineInputAssemblyStateCreateInfo PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO{
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
VkPipelineInputAssemblyStateCreateInfo GetPipelineInputAssemblyStateCreateInfo(const Device& device) {
|
||||||
.pNext = nullptr,
|
return VkPipelineInputAssemblyStateCreateInfo{
|
||||||
.flags = 0,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
.pNext = nullptr,
|
||||||
.primitiveRestartEnable = VK_FALSE,
|
.flags = 0,
|
||||||
};
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||||
|
.primitiveRestartEnable = device.IsMoltenVK() ? VK_TRUE : VK_FALSE,
|
||||||
|
};
|
||||||
|
}
|
||||||
constexpr VkPipelineViewportStateCreateInfo PIPELINE_VIEWPORT_STATE_CREATE_INFO{
|
constexpr VkPipelineViewportStateCreateInfo PIPELINE_VIEWPORT_STATE_CREATE_INFO{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -802,6 +805,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
|
||||||
.pAttachments = &blend_attachment,
|
.pAttachments = &blend_attachment,
|
||||||
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
|
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
|
||||||
};
|
};
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
blit_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -809,7 +813,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceColorPipeline(const BlitImagePipelineKe
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
@ -833,6 +837,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
|
||||||
}
|
}
|
||||||
blit_depth_stencil_keys.push_back(key);
|
blit_depth_stencil_keys.push_back(key);
|
||||||
const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag);
|
const std::array stages = MakeStages(*full_screen_vert, *blit_depth_stencil_frag);
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
blit_depth_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -840,7 +845,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
@ -885,6 +890,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel
|
||||||
.pAttachments = &color_blend_attachment_state,
|
.pAttachments = &color_blend_attachment_state,
|
||||||
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
|
.blendConstants = {0.0f, 0.0f, 0.0f, 0.0f},
|
||||||
};
|
};
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
clear_color_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -892,7 +898,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearColorPipeline(const BlitImagePipel
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
@ -940,6 +946,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
|
||||||
.minDepthBounds = 0.0f,
|
.minDepthBounds = 0.0f,
|
||||||
.maxDepthBounds = 0.0f,
|
.maxDepthBounds = 0.0f,
|
||||||
};
|
};
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
clear_stencil_pipelines.push_back(device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -947,7 +954,7 @@ VkPipeline BlitImageHelper::FindOrEmplaceClearStencilPipeline(
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
@ -970,6 +977,7 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
|
||||||
}
|
}
|
||||||
VkShaderModule frag_shader = *convert_float_to_depth_frag;
|
VkShaderModule frag_shader = *convert_float_to_depth_frag;
|
||||||
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
|
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -977,7 +985,7 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
@ -999,6 +1007,7 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend
|
||||||
}
|
}
|
||||||
VkShaderModule frag_shader = *convert_depth_to_float_frag;
|
VkShaderModule frag_shader = *convert_depth_to_float_frag;
|
||||||
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
|
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -1006,7 +1015,7 @@ void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRend
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
@ -1029,6 +1038,7 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const std::array stages = MakeStages(*full_screen_vert, *module);
|
const std::array stages = MakeStages(*full_screen_vert, *module);
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -1036,7 +1046,7 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
@ -1070,6 +1080,7 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende
|
||||||
VkShaderModule frag_shader =
|
VkShaderModule frag_shader =
|
||||||
is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
|
is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
|
||||||
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
|
const std::array stages = MakeStages(*full_screen_vert, frag_shader);
|
||||||
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci = GetPipelineInputAssemblyStateCreateInfo(device);
|
||||||
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
pipeline = device.GetLogical().CreateGraphicsPipeline({
|
||||||
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
|
@ -1077,7 +1088,7 @@ void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass rende
|
||||||
.stageCount = static_cast<u32>(stages.size()),
|
.stageCount = static_cast<u32>(stages.size()),
|
||||||
.pStages = stages.data(),
|
.pStages = stages.data(),
|
||||||
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
.pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
|
||||||
.pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.pInputAssemblyState = &input_assembly_ci,
|
||||||
.pTessellationState = nullptr,
|
.pTessellationState = nullptr,
|
||||||
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
.pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
|
||||||
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
.pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
|
||||||
|
|
|
@ -400,12 +400,12 @@ static vk::Pipeline CreateWrappedPipelineImpl(
|
||||||
.pVertexAttributeDescriptions = nullptr,
|
.pVertexAttributeDescriptions = nullptr,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
|
const VkPipelineInputAssemblyStateCreateInfo input_assembly_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
|
||||||
.pNext = nullptr,
|
.pNext = nullptr,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
|
||||||
.primitiveRestartEnable = VK_FALSE,
|
.primitiveRestartEnable = device.IsMoltenVK() ? VK_TRUE : VK_FALSE,
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr VkPipelineViewportStateCreateInfo viewport_state_ci{
|
constexpr VkPipelineViewportStateCreateInfo viewport_state_ci{
|
||||||
|
|
|
@ -635,14 +635,16 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.topology = input_assembly_topology,
|
.topology = input_assembly_topology,
|
||||||
.primitiveRestartEnable =
|
.primitiveRestartEnable =
|
||||||
dynamic.primitive_restart_enable != 0 &&
|
// MoltenVK/Metal always has primitive restart enabled and cannot disable it
|
||||||
|
device.IsMoltenVK() ? VK_TRUE :
|
||||||
|
(dynamic.primitive_restart_enable != 0 &&
|
||||||
((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
||||||
device.IsTopologyListPrimitiveRestartSupported()) ||
|
device.IsTopologyListPrimitiveRestartSupported()) ||
|
||||||
SupportsPrimitiveRestart(input_assembly_topology) ||
|
SupportsPrimitiveRestart(input_assembly_topology) ||
|
||||||
(input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
(input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
|
||||||
device.IsPatchListPrimitiveRestartSupported()))
|
device.IsPatchListPrimitiveRestartSupported()))
|
||||||
? VK_TRUE
|
? VK_TRUE
|
||||||
: VK_FALSE,
|
: VK_FALSE),
|
||||||
};
|
};
|
||||||
const VkPipelineTessellationStateCreateInfo tessellation_ci{
|
const VkPipelineTessellationStateCreateInfo tessellation_ci{
|
||||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
|
||||||
|
|
|
@ -725,6 +725,11 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
dynamic_state3_enables = true;
|
dynamic_state3_enables = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_mvk && Settings::values.dyna_state.GetValue() != 0) {
|
||||||
|
LOG_WARNING(Render_Vulkan, "MoltenVK detected: Forcing dynamic state to 0 to prevent black screen issues");
|
||||||
|
Settings::values.dyna_state.SetValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
if (Settings::values.dyna_state.GetValue() == 0) {
|
if (Settings::values.dyna_state.GetValue() == 0) {
|
||||||
must_emulate_scaled_formats = true;
|
must_emulate_scaled_formats = true;
|
||||||
LOG_INFO(Render_Vulkan, "Dynamic state is disabled (dyna_state = 0), forcing scaled format emulation ON");
|
LOG_INFO(Render_Vulkan, "Dynamic state is disabled (dyna_state = 0), forcing scaled format emulation ON");
|
||||||
|
@ -1090,8 +1095,15 @@ bool Device::GetSuitability(bool requires_swapchain) {
|
||||||
// Some features are mandatory. Check those.
|
// Some features are mandatory. Check those.
|
||||||
#define CHECK_FEATURE(feature, name) \
|
#define CHECK_FEATURE(feature, name) \
|
||||||
if (!features.feature.name) { \
|
if (!features.feature.name) { \
|
||||||
LOG_ERROR(Render_Vulkan, "Missing required feature {}", #name); \
|
if (IsMoltenVK() && (strcmp(#name, "geometryShader") == 0 || \
|
||||||
suitable = false; \
|
strcmp(#name, "logicOp") == 0 || \
|
||||||
|
strcmp(#name, "shaderCullDistance") == 0 || \
|
||||||
|
strcmp(#name, "wideLines") == 0)) { \
|
||||||
|
LOG_INFO(Render_Vulkan, "MoltenVK missing feature {} - using fallback", #name); \
|
||||||
|
} else { \
|
||||||
|
LOG_ERROR(Render_Vulkan, "Missing required feature {}", #name); \
|
||||||
|
suitable = false; \
|
||||||
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOG_FEATURE(feature, name) \
|
#define LOG_FEATURE(feature, name) \
|
||||||
|
|
|
@ -717,6 +717,10 @@ public:
|
||||||
return properties.driver.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
|
return properties.driver.driverID == VK_DRIVER_ID_NVIDIA_PROPRIETARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsMoltenVK() const noexcept {
|
||||||
|
return properties.driver.driverID == VK_DRIVER_ID_MOLTENVK;
|
||||||
|
}
|
||||||
|
|
||||||
NvidiaArchitecture GetNvidiaArch() const noexcept {
|
NvidiaArchitecture GetNvidiaArch() const noexcept {
|
||||||
return nvidia_arch;
|
return nvidia_arch;
|
||||||
}
|
}
|
||||||
|
|
|
@ -580,6 +580,7 @@ DescriptorSets DescriptorPool::Allocate(const VkDescriptorSetAllocateInfo& ai) c
|
||||||
case VK_SUCCESS:
|
case VK_SUCCESS:
|
||||||
return DescriptorSets(std::move(sets), num, owner, handle, *dld);
|
return DescriptorSets(std::move(sets), num, owner, handle, *dld);
|
||||||
case VK_ERROR_OUT_OF_POOL_MEMORY:
|
case VK_ERROR_OUT_OF_POOL_MEMORY:
|
||||||
|
case VK_ERROR_FRAGMENTED_POOL:
|
||||||
return {};
|
return {};
|
||||||
default:
|
default:
|
||||||
throw Exception(result);
|
throw Exception(result);
|
||||||
|
@ -604,6 +605,7 @@ CommandBuffers CommandPool::Allocate(std::size_t num_buffers, VkCommandBufferLev
|
||||||
case VK_SUCCESS:
|
case VK_SUCCESS:
|
||||||
return CommandBuffers(std::move(buffers), num_buffers, owner, handle, *dld);
|
return CommandBuffers(std::move(buffers), num_buffers, owner, handle, *dld);
|
||||||
case VK_ERROR_OUT_OF_POOL_MEMORY:
|
case VK_ERROR_OUT_OF_POOL_MEMORY:
|
||||||
|
case VK_ERROR_FRAGMENTED_POOL:
|
||||||
return {};
|
return {};
|
||||||
default:
|
default:
|
||||||
throw Exception(result);
|
throw Exception(result);
|
||||||
|
|
|
@ -60,6 +60,10 @@ void ConfigureGraphicsExtensions::Setup(const ConfigurationShared::Builder& buil
|
||||||
if (setting->Id() == Settings::values.dyna_state.Id()) {
|
if (setting->Id() == Settings::values.dyna_state.Id()) {
|
||||||
widget->slider->setTickInterval(1);
|
widget->slider->setTickInterval(1);
|
||||||
widget->slider->setTickPosition(QSlider::TicksAbove);
|
widget->slider->setTickPosition(QSlider::TicksAbove);
|
||||||
|
#ifdef __APPLE__
|
||||||
|
widget->setEnabled(false);
|
||||||
|
widget->setToolTip(tr("Extended Dynamic State is disabled on macOS due to MoltenVK compatibility issues that cause black screens."));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue