Compare commits

..

15 Commits

Author SHA1 Message Date
Morph
af89f7683d externals: Update dynarmic to 28714ee7
Reduces compilation times on MSVC.
2021-12-30 22:28:27 -05:00
bunnei
279c7bcc1a Merge pull request #7618 from goldenx86/patch-4
Increase boost requirement to 1.78.0
2021-12-28 16:25:37 -08:00
bunnei
f67605e6aa Merge pull request #7622 from ameerj/vk-rescale-invalid-ptr
vk_texture_cache: Fix invalidated pointer access
2021-12-28 00:46:37 -08:00
bunnei
9a0648ff0a Merge pull request #7621 from bunnei/set-mem-perm
core: hle: kernel: Implement SetMemoryPermission.
2021-12-27 23:33:11 -08:00
bunnei
c9e4acc4e2 Merge pull request #7630 from ameerj/glasm-get-int
emit_glasm_context_get_set: Fix GetAttribute return value type.
2021-12-27 16:35:11 -08:00
bunnei
292dfac25e Merge pull request #7620 from bunnei/kernel-thread-x18
core: hle: kernel: KThread: X18 should be a cryptographically random number.
2021-12-25 00:42:54 -08:00
ameerj
37addf7a94 emit_glasm_context_get_set: Fix GetAttribute return value type.
GetAttribute expects an F32 result type at the IR level, this fixes the return value of attributes which were not returning an F32
2021-12-24 20:45:07 -05:00
bunnei
8a48c4ed1c Merge pull request #7623 from ameerj/unused-func
blit_image: Remove unused function
2021-12-23 22:21:28 -08:00
ameerj
cbc0f0a66e blit_image: Remove unused function 2021-12-23 21:06:32 -05:00
ameerj
481b210c0d vk_texture_cache: Fix invalidated pointer access
The vulkan ImageView held a reference to its source image for rescale status checking. This pointer is sometimes invalidated when the texture cache slot_images container is resized.
To avoid an invalid pointer dereference, the ImageView now holds a reference to the container itself.
2021-12-23 20:55:48 -05:00
bunnei
4e7a6639d2 core: hle: kernel: Implement SetMemoryPermission.
- Not seen in any games yet, but validated with kernel tests.
2021-12-23 01:10:36 -08:00
bunnei
a0c7d93b84 core: hle: kernel: KThread: X18 should be a cryptographically random number.
- This was added with firmware 11.0.0 (https://switchbrew.org/wiki/11.0.0).
    - X18 is OR'd by kernel with 1, to make sure it is odd.
2021-12-23 00:03:39 -08:00
bunnei
516325eba8 Merge pull request #7614 from liushuyu/fix-linux-inhibit
main: Fix wake lock (prevent sleep) in Flatpak
2021-12-22 16:53:54 -08:00
liushuyu
14fc1bec17 main: reword inhibit reason 2021-12-22 02:33:01 -07:00
liushuyu
fa7abafa5f main: fix wake lock in Flatpak ...
... by using the XDP system
2021-12-22 02:27:09 -07:00
18 changed files with 160 additions and 65 deletions

View File

@@ -249,7 +249,7 @@ if(ENABLE_QT)
# Check for system Qt on Linux, fallback to bundled Qt
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if (NOT YUZU_USE_BUNDLED_QT)
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets)
find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets DBus)
endif()
if (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)
# Check for dependencies, then enable bundled Qt download

View File

@@ -806,6 +806,33 @@ ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite);
return ResultSuccess;
}
ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
Svc::MemoryPermission svc_perm) {
const size_t num_pages = size / PageSize;
// Lock the table.
std::lock_guard lock{page_table_lock};
// Verify we can change the memory permission.
KMemoryState old_state;
KMemoryPermission old_perm;
R_TRY(this->CheckMemoryState(
std::addressof(old_state), std::addressof(old_perm), nullptr, addr, size,
KMemoryState::FlagCanReprotect, KMemoryState::FlagCanReprotect, KMemoryPermission::None,
KMemoryPermission::None, KMemoryAttribute::All, KMemoryAttribute::None));
// Determine new perm.
const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm);
R_SUCCEED_IF(old_perm == new_perm);
// Perform mapping operation.
R_TRY(Operate(addr, num_pages, new_perm, OperationType::ChangePermissions));
// Update the blocks.
block_manager->Update(addr, num_pages, old_state, new_perm, KMemoryAttribute::None);
return ResultSuccess;
}

View File

@@ -47,6 +47,7 @@ public:
KMemoryInfo QueryInfo(VAddr addr);
ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm);
ResultCode ResetTransferMemory(VAddr addr, std::size_t size);
ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm);
ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
KMemoryAttribute value);
ResultCode SetHeapCapacity(std::size_t new_heap_capacity);

View File

@@ -26,6 +26,7 @@
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
#include "core/hle/kernel/k_system_control.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/k_thread_queue.h"
#include "core/hle/kernel/kernel.h"
@@ -50,6 +51,7 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
VAddr entry_point, u64 arg) {
context = {};
context.cpu_registers[0] = arg;
context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
context.pc = entry_point;
context.sp = stack_top;
// TODO(merry): Perform a hardware test to determine the below value.

View File

@@ -164,6 +164,36 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
return result;
}
constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
switch (perm) {
case MemoryPermission::None:
case MemoryPermission::Read:
case MemoryPermission::ReadWrite:
return true;
default:
return false;
}
}
static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size,
MemoryPermission perm) {
// Validate address / size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Validate the permission.
R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
// Validate that the region is in range for the current process.
auto& page_table = system.Kernel().CurrentProcess()->PageTable();
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
// Set the memory attribute.
return page_table.SetMemoryPermission(address, size, perm);
}
static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
u32 attribute) {
LOG_DEBUG(Kernel_SVC,
@@ -2724,7 +2754,7 @@ static const FunctionDef SVC_Table_32[] = {
static const FunctionDef SVC_Table_64[] = {
{0x00, nullptr, "Unknown"},
{0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
{0x02, nullptr, "SetMemoryPermission"},
{0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
{0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
{0x04, SvcWrap64<MapMemory>, "MapMemory"},
{0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},

View File

@@ -249,6 +249,14 @@ void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
}
// Used by SetMemoryPermission
template <ResultCode func(Core::System&, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<Svc::MemoryPermission>(Param(system, 2)))
.raw);
}
// Used by MapSharedMemory
template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {

View File

@@ -86,7 +86,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
}
switch (attr) {
case IR::Attribute::PrimitiveId:
ctx.Add("MOV.S {}.x,primitive.id;", inst);
ctx.Add("MOV.F {}.x,primitive.id;", inst);
break;
case IR::Attribute::PositionX:
case IR::Attribute::PositionY:
@@ -113,13 +113,13 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
ctx.Add("MOV.F {}.x,vertex.tesscoord.{};", inst, swizzle);
break;
case IR::Attribute::InstanceId:
ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name);
ctx.Add("MOV.F {}.x,{}.instance;", inst, ctx.attrib_name);
break;
case IR::Attribute::VertexId:
ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name);
ctx.Add("MOV.F {}.x,{}.id;", inst, ctx.attrib_name);
break;
case IR::Attribute::FrontFace:
ctx.Add("CMP.S {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name);
ctx.Add("CMP.F {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name);
break;
default:
throw NotImplementedException("Get attribute {}", attr);

View File

@@ -1047,7 +1047,7 @@ bool Image::ScaleDown(bool ignore) {
}
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image)
ImageId image_id_, Image& image, const SlotVector<Image>&)
: VideoCommon::ImageViewBase{info, image.info, image_id_}, views{runtime.null_image_views} {
const Device& device = runtime.device;
if (True(image.flags & ImageFlagBits::Converted)) {

View File

@@ -36,6 +36,7 @@ using VideoCommon::ImageViewType;
using VideoCommon::NUM_RT;
using VideoCommon::Region2D;
using VideoCommon::RenderTargets;
using VideoCommon::SlotVector;
struct ImageBufferMap {
~ImageBufferMap();
@@ -234,7 +235,8 @@ class ImageView : public VideoCommon::ImageViewBase {
friend Image;
public:
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&,
const SlotVector<Image>&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
const VideoCommon::ImageViewInfo&, GPUVAddr);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,

View File

@@ -518,53 +518,6 @@ void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_frameb
scheduler.InvalidateState();
}
void BlitImageHelper::ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
ImageView& src_image_view, u32 up_scale, u32 down_shift) {
const VkPipelineLayout layout = *one_texture_pipeline_layout;
const VkImageView src_view = src_image_view.ColorView();
const VkSampler sampler = *nearest_sampler;
const VkExtent2D extent{
.width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U),
.height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
};
scheduler.RequestRenderpass(dst_framebuffer);
scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift,
this](vk::CommandBuffer cmdbuf) {
const VkOffset2D offset{
.x = 0,
.y = 0,
};
const VkViewport viewport{
.x = 0.0f,
.y = 0.0f,
.width = static_cast<float>(extent.width),
.height = static_cast<float>(extent.height),
.minDepth = 0.0f,
.maxDepth = 0.0f,
};
const VkRect2D scissor{
.offset = offset,
.extent = extent,
};
const PushConstants push_constants{
.tex_scale = {viewport.width, viewport.height},
.tex_offset = {0.0f, 0.0f},
};
const VkDescriptorSet descriptor_set = one_texture_descriptor_allocator.Commit();
UpdateOneTextureDescriptorSet(device, descriptor_set, sampler, src_view);
// TODO: Barriers
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptor_set,
nullptr);
cmdbuf.SetViewport(0, viewport);
cmdbuf.SetScissor(0, scissor);
cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
cmdbuf.Draw(3, 1, 0, 0);
});
scheduler.InvalidateState();
}
void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
ImageView& src_image_view) {
const VkPipelineLayout layout = *two_textures_pipeline_layout;

View File

@@ -60,9 +60,6 @@ private:
void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
const ImageView& src_image_view);
void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
ImageView& src_image_view, u32 up_scale, u32 down_shift);
void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
ImageView& src_image_view);

View File

@@ -1473,8 +1473,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image)
: VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
src_image{&image}, image_handle{image.Handle()},
samples(ConvertSampleCount(image.info.num_samples)) {
image_handle{image.Handle()}, samples(ConvertSampleCount(image.info.num_samples)) {
using Shader::TextureType;
const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
@@ -1557,6 +1556,12 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
}
}
ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
ImageId image_id_, Image& image, const SlotVector<Image>& slot_imgs)
: ImageView{runtime, info, image_id_, image} {
slot_images = &slot_imgs;
}
ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_)
: VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_},
@@ -1613,10 +1618,12 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
}
bool ImageView::IsRescaled() const noexcept {
if (!src_image) {
if (!slot_images) {
return false;
}
return src_image->IsRescaled();
const auto& slots = *slot_images;
const auto& src_image = slots[image_id];
return src_image.IsRescaled();
}
vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {

View File

@@ -23,6 +23,7 @@ using VideoCommon::ImageId;
using VideoCommon::NUM_RT;
using VideoCommon::Region2D;
using VideoCommon::RenderTargets;
using VideoCommon::SlotVector;
using VideoCore::Surface::PixelFormat;
class ASTCDecoderPass;
@@ -170,6 +171,8 @@ private:
class ImageView : public VideoCommon::ImageViewBase {
public:
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&,
const SlotVector<Image>&);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
const VideoCommon::ImageViewInfo&, GPUVAddr);
explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&);
@@ -226,7 +229,7 @@ private:
[[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
const Device* device = nullptr;
const Image* src_image{};
const SlotVector<Image>* slot_images = nullptr;
std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
std::unique_ptr<StorageViews> storage_views;

View File

@@ -1397,7 +1397,8 @@ ImageViewId TextureCache<P>::FindOrEmplaceImageView(ImageId image_id, const Imag
if (const ImageViewId image_view_id = image.FindView(info); image_view_id) {
return image_view_id;
}
const ImageViewId image_view_id = slot_image_views.insert(runtime, info, image_id, image);
const ImageViewId image_view_id =
slot_image_views.insert(runtime, info, image_id, image, slot_images);
image.InsertView(info, image_view_id);
return image_view_id;
}

View File

@@ -251,6 +251,9 @@ target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include)
if (NOT WIN32)
target_include_directories(yuzu PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS})
endif()
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
target_link_libraries(yuzu PRIVATE Qt5::DBus)
endif()
target_compile_definitions(yuzu PRIVATE
# Use QStringBuilder for string concatenation to reduce

View File

@@ -1236,11 +1236,58 @@ void GMainWindow::OnDisplayTitleBars(bool show) {
}
}
#ifdef __linux__
static std::optional<QDBusObjectPath> HoldWakeLockLinux(u32 window_id = 0) {
if (!QDBusConnection::sessionBus().isConnected()) {
return {};
}
// reference: https://flatpak.github.io/xdg-desktop-portal/#gdbus-org.freedesktop.portal.Inhibit
QDBusInterface xdp(QString::fromLatin1("org.freedesktop.portal.Desktop"),
QString::fromLatin1("/org/freedesktop/portal/desktop"),
QString::fromLatin1("org.freedesktop.portal.Inhibit"));
if (!xdp.isValid()) {
LOG_WARNING(Frontend, "Couldn't connect to XDP D-Bus endpoint");
return {};
}
QVariantMap options = {};
//: TRANSLATORS: This string is shown to the user to explain why yuzu needs to prevent the
//: computer from sleeping
options.insert(QString::fromLatin1("reason"),
QCoreApplication::translate("GMainWindow", "yuzu is running a game"));
// 0x4: Suspend lock; 0x8: Idle lock
QDBusReply<QDBusObjectPath> reply =
xdp.call(QString::fromLatin1("Inhibit"),
QString::fromLatin1("x11:") + QString::number(window_id, 16), 12U, options);
if (reply.isValid()) {
return reply.value();
}
LOG_WARNING(Frontend, "Couldn't read Inhibit reply from XDP: {}",
reply.error().message().toStdString());
return {};
}
static void ReleaseWakeLockLinux(QDBusObjectPath lock) {
if (!QDBusConnection::sessionBus().isConnected()) {
return;
}
QDBusInterface unlocker(QString::fromLatin1("org.freedesktop.portal.Desktop"), lock.path(),
QString::fromLatin1("org.freedesktop.portal.Request"));
unlocker.call(QString::fromLatin1("Close"));
}
#endif // __linux__
void GMainWindow::PreventOSSleep() {
#ifdef _WIN32
SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
#elif defined(HAVE_SDL2)
SDL_DisableScreenSaver();
#ifdef __linux__
auto reply = HoldWakeLockLinux(winId());
if (reply) {
wake_lock = std::move(reply.value());
}
#endif
#endif
}
@@ -1249,6 +1296,11 @@ void GMainWindow::AllowOSSleep() {
SetThreadExecutionState(ES_CONTINUOUS);
#elif defined(HAVE_SDL2)
SDL_EnableScreenSaver();
#ifdef __linux__
if (!wake_lock.path().isEmpty()) {
ReleaseWakeLockLinux(wake_lock);
}
#endif
#endif
}

View File

@@ -17,6 +17,12 @@
#include "yuzu/compatibility_list.h"
#include "yuzu/hotkeys.h"
#ifdef __linux__
#include <QVariant>
#include <QtDBus/QDBusInterface>
#include <QtDBus/QtDBus>
#endif
class Config;
class EmuThread;
class GameList;
@@ -394,6 +400,9 @@ private:
// Applets
QtSoftwareKeyboardDialog* software_keyboard = nullptr;
#ifdef __linux__
QDBusObjectPath wake_lock{};
#endif
protected:
void dropEvent(QDropEvent* event) override;