mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-23 10:21:51 +01:00
Validation Layer Filter + Fix Texture
, GPU & PresentationEngine
bugs
This commit implements a filter by type for any validation layer output, this allows filtering out any logs which may be unnecessary and additionally triggering a breakpoint as required. An issue concerning the `NDEBUG` flag never being set was fixed, it's now supplied as a release compiler flag. The issue can manifest itself by always relying on a validation layer even though it shouldn't on release, this is why the validation layer was mistakenly disabled entirely previously by using `#ifndef` rather than `#ifdef`. An issue with the initial layout of a texture being supplied as neither `VK_IMAGE_LAYOUT_UNDEFINED` or `VK_IMAGE_LAYOUT_PREINITIALIZED` was fixed, these cases are now handled by transitioning to those layouts after creating the image rather than supplying it within `initialLayout`. Another issue was fixed regarding not maintaining a transformation after a surface has been destroyed and recreated existed and manifested itself when the user would go out of the app and come back in, they would see the surface having an identity transformation rather than the desired one.
This commit is contained in:
parent
54908afc44
commit
bee28aaf0d
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@ -60,7 +60,7 @@
|
||||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
2
.idea/scopes/SkylineNative.xml
generated
2
.idea/scopes/SkylineNative.xml
generated
@ -1,3 +1,3 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="SkylineNative" pattern="file[skyline.app]:src/main/cpp//*.cpp||file[skyline.app]:src/main/cpp//*.h||file[skyline.app]:src/main/cpp//*.S" />
|
||||
<scope name="SkylineNative" pattern="file[skyline.app]:src/main/cpp//*.cpp||file[skyline.app]:src/main/cpp//*.h||file[skyline.app]:src/main/cpp//*.S||file[skyline.app]:src/main/cpp//*.natvis" />
|
||||
</component>
|
@ -10,11 +10,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED TRUE)
|
||||
|
||||
set(source_DIR ${CMAKE_SOURCE_DIR}/src/main/cpp)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-strict-aliasing")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -flto=full -fno-stack-protector -Wno-unused-command-line-argument")
|
||||
if (uppercase_CMAKE_BUILD_TYPE STREQUAL "RELEASE")
|
||||
add_compile_definitions(NDEBUG)
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
|
||||
endif ()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Ofast -flto=full -fno-stack-protector -Wno-unused-command-line-argument -DNDEBUG")
|
||||
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE)
|
||||
|
||||
# {fmt}
|
||||
add_subdirectory("libraries/fmt")
|
||||
|
@ -13,7 +13,7 @@ namespace skyline::gpu {
|
||||
.apiVersion = VkApiVersion,
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
#ifdef NDEBUG
|
||||
constexpr std::array<const char *, 0> requiredLayers{};
|
||||
#else
|
||||
constexpr std::array<const char *, 1> requiredLayers{
|
||||
@ -82,7 +82,33 @@ namespace skyline::gpu {
|
||||
Logger::LogLevel::Error, // VK_DEBUG_REPORT_ERROR_BIT_EXT
|
||||
Logger::LogLevel::Debug, // VK_DEBUG_REPORT_DEBUG_BIT_EXT
|
||||
};
|
||||
|
||||
#define IGNORE_VALIDATION(string) \
|
||||
case util::Hash(string): \
|
||||
if(string == type) \
|
||||
return VK_FALSE; \
|
||||
else \
|
||||
break
|
||||
|
||||
#define DEBUG_VALIDATION(string) \
|
||||
case util::Hash(string): \
|
||||
if(string == type) \
|
||||
__builtin_debugtrap(); \
|
||||
break
|
||||
|
||||
std::string_view type(message);
|
||||
auto first{type.find_first_of('[') + 2};
|
||||
type = type.substr(first, type.find_first_of(']', first) - 4);
|
||||
|
||||
switch (util::Hash(type)) {
|
||||
IGNORE_VALIDATION("UNASSIGNED-CoreValidation-SwapchainPreTransform"); // We handle transformation via Android APIs directly
|
||||
IGNORE_VALIDATION("UNASSIGNED-GeneralParameterPerfWarn-SuboptimalSwapchain"); // Same as SwapchainPreTransform
|
||||
}
|
||||
|
||||
#undef IGNORE_TYPE
|
||||
|
||||
logger->Write(severityLookup.at(std::countr_zero(static_cast<u32>(flags))), util::Format("Vk{}:{}[0x{:X}]:I{}:L{}: {}", layerPrefix, vk::to_string(vk::DebugReportObjectTypeEXT(objectType)), object, messageCode, location, message));
|
||||
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
|
@ -190,6 +190,9 @@ namespace skyline::gpu {
|
||||
if (windowScalingMode != NativeWindowScalingMode::ScaleToWindow && (result = window->perform(window, NATIVE_WINDOW_SET_SCALING_MODE, static_cast<i32>(windowScalingMode))))
|
||||
throw exception("Setting the layer scaling mode to '{}' failed with {}", ToString(windowScalingMode), result);
|
||||
|
||||
if (windowTransform != NativeWindowTransform::Identity && (result = window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TRANSFORM, static_cast<i32>(windowTransform))))
|
||||
throw exception("Setting the buffer transform to '{}' failed with {}", ToString(windowTransform), result);
|
||||
|
||||
if ((result = window->perform(window, NATIVE_WINDOW_ENABLE_FRAME_TIMESTAMPS, true)))
|
||||
throw exception("Enabling frame timestamps failed with {}", result);
|
||||
|
||||
@ -226,6 +229,8 @@ namespace skyline::gpu {
|
||||
windowTransform = transform;
|
||||
}
|
||||
|
||||
gpu.vkDevice.resetFences(*acquireFence);
|
||||
|
||||
std::pair<vk::Result, u32> nextImage;
|
||||
while (nextImage = vkSwapchain->acquireNextImage(std::numeric_limits<u64>::max(), {}, *acquireFence), nextImage.first != vk::Result::eSuccess) [[unlikely]] {
|
||||
if (nextImage.first == vk::Result::eSuboptimalKHR)
|
||||
|
@ -7,19 +7,38 @@
|
||||
#include "texture.h"
|
||||
|
||||
namespace skyline::gpu {
|
||||
Texture::Texture(GPU &gpu, BackingType &&backing, GuestTexture guest, texture::Dimensions dimensions, texture::Format format, vk::ImageLayout layout, vk::ImageTiling tiling, u32 mipLevels, u32 layerCount, vk::SampleCountFlagBits sampleCount) : gpu(gpu), backing(std::move(backing)), layout(layout), guest(std::move(guest)), dimensions(dimensions), format(format), tiling(tiling), mipLevels(mipLevels), layerCount(layerCount), sampleCount(sampleCount) {
|
||||
Texture::Texture(GPU &gpu, BackingType &&backing, GuestTexture guest, texture::Dimensions dimensions, texture::Format format, vk::ImageLayout layout, vk::ImageTiling tiling, u32 mipLevels, u32 layerCount, vk::SampleCountFlagBits sampleCount)
|
||||
: gpu(gpu),
|
||||
backing(std::move(backing)),
|
||||
layout(layout),
|
||||
guest(std::move(guest)),
|
||||
dimensions(dimensions),
|
||||
format(format),
|
||||
tiling(tiling),
|
||||
mipLevels(mipLevels),
|
||||
layerCount(layerCount),
|
||||
sampleCount(sampleCount) {
|
||||
if (GetBacking())
|
||||
SynchronizeHost();
|
||||
}
|
||||
|
||||
Texture::Texture(GPU &gpu, BackingType &&backing, texture::Dimensions dimensions, texture::Format format, vk::ImageLayout layout, vk::ImageTiling tiling, u32 mipLevels, u32 layerCount, vk::SampleCountFlagBits sampleCount) : gpu(gpu), backing(std::move(backing)), dimensions(dimensions), format(format), layout(layout), tiling(tiling), mipLevels(mipLevels), layerCount(layerCount), sampleCount(sampleCount) {}
|
||||
Texture::Texture(GPU &gpu, BackingType &&backing, texture::Dimensions dimensions, texture::Format format, vk::ImageLayout layout, vk::ImageTiling tiling, u32 mipLevels, u32 layerCount, vk::SampleCountFlagBits sampleCount)
|
||||
: gpu(gpu),
|
||||
backing(std::move(backing)),
|
||||
dimensions(dimensions),
|
||||
format(format),
|
||||
layout(layout),
|
||||
tiling(tiling),
|
||||
mipLevels(mipLevels),
|
||||
layerCount(layerCount),
|
||||
sampleCount(sampleCount) {}
|
||||
|
||||
Texture::Texture(GPU &pGpu, GuestTexture pGuest)
|
||||
: gpu(pGpu),
|
||||
guest(std::move(pGuest)),
|
||||
dimensions(guest->dimensions),
|
||||
format(guest->format),
|
||||
layout(vk::ImageLayout::eGeneral),
|
||||
layout(vk::ImageLayout::eUndefined),
|
||||
tiling((guest->tileConfig.mode == texture::TileMode::Block) ? vk::ImageTiling::eOptimal : vk::ImageTiling::eLinear),
|
||||
mipLevels(1),
|
||||
layerCount(guest->layerCount),
|
||||
@ -39,9 +58,18 @@ namespace skyline::gpu {
|
||||
.initialLayout = layout,
|
||||
};
|
||||
backing = tiling != vk::ImageTiling::eLinear ? gpu.memory.AllocateImage(imageCreateInfo) : gpu.memory.AllocateMappedImage(imageCreateInfo);
|
||||
TransitionLayout(vk::ImageLayout::eGeneral);
|
||||
}
|
||||
|
||||
Texture::Texture(GPU &gpu, texture::Dimensions dimensions, texture::Format format, vk::ImageLayout initialLayout, vk::ImageUsageFlags usage, vk::ImageTiling tiling, u32 mipLevels, u32 layerCount, vk::SampleCountFlagBits sampleCount) : gpu(gpu), dimensions(dimensions), format(format), layout(initialLayout), tiling(tiling), mipLevels(mipLevels), layerCount(layerCount), sampleCount(sampleCount) {
|
||||
Texture::Texture(GPU &gpu, texture::Dimensions dimensions, texture::Format format, vk::ImageLayout initialLayout, vk::ImageUsageFlags usage, vk::ImageTiling tiling, u32 mipLevels, u32 layerCount, vk::SampleCountFlagBits sampleCount)
|
||||
: gpu(gpu),
|
||||
dimensions(dimensions),
|
||||
format(format),
|
||||
layout(initialLayout == vk::ImageLayout::ePreinitialized ? vk::ImageLayout::ePreinitialized : vk::ImageLayout::eUndefined),
|
||||
tiling(tiling),
|
||||
mipLevels(mipLevels),
|
||||
layerCount(layerCount),
|
||||
sampleCount(sampleCount) {
|
||||
vk::ImageCreateInfo imageCreateInfo{
|
||||
.imageType = dimensions.GetType(),
|
||||
.format = *format,
|
||||
@ -54,9 +82,11 @@ namespace skyline::gpu {
|
||||
.sharingMode = vk::SharingMode::eExclusive,
|
||||
.queueFamilyIndexCount = 1,
|
||||
.pQueueFamilyIndices = &gpu.vkQueueFamilyIndex,
|
||||
.initialLayout = initialLayout,
|
||||
.initialLayout = layout,
|
||||
};
|
||||
backing = tiling != vk::ImageTiling::eLinear ? gpu.memory.AllocateImage(imageCreateInfo) : gpu.memory.AllocateMappedImage(imageCreateInfo);
|
||||
if (initialLayout != layout)
|
||||
TransitionLayout(initialLayout);
|
||||
}
|
||||
|
||||
bool Texture::WaitOnBacking() {
|
||||
@ -354,7 +384,6 @@ namespace skyline::gpu {
|
||||
TextureView::TextureView(std::shared_ptr<Texture> backing, vk::ImageViewType type, vk::ImageSubresourceRange range, texture::Format format, vk::ComponentMapping mapping) : backing(std::move(backing)), type(type), format(format), mapping(mapping), range(range) {}
|
||||
|
||||
vk::ImageView TextureView::GetView() {
|
||||
/*
|
||||
if (view)
|
||||
return **view;
|
||||
|
||||
@ -369,14 +398,21 @@ namespace skyline::gpu {
|
||||
}
|
||||
}()};
|
||||
|
||||
return *view.emplace(backing->gpu.vkDevice, vk::ImageViewCreateInfo{
|
||||
vk::ImageViewCreateInfo createInfo{
|
||||
.image = backing->GetBacking(),
|
||||
.viewType = vk::ImageViewType::eCube,
|
||||
.viewType = viewType,
|
||||
.format = format ? *format : *backing->format,
|
||||
.components = mapping,
|
||||
.subresourceRange = range,
|
||||
});
|
||||
*/
|
||||
throw exception("TODO: TextureView::GetView");
|
||||
};
|
||||
|
||||
auto &views{backing->views};
|
||||
auto iterator{std::find_if(views.begin(), views.end(), [&](const std::pair<vk::ImageViewCreateInfo, vk::raii::ImageView> &item) {
|
||||
return item.first == createInfo;
|
||||
})};
|
||||
if (iterator != views.end())
|
||||
return *iterator->second;
|
||||
|
||||
return *views.emplace_back(createInfo, vk::raii::ImageView(backing->gpu.vkDevice, createInfo)).second;
|
||||
}
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ namespace skyline::gpu {
|
||||
|
||||
/**
|
||||
* @brief A wrapper around a pointer to underlying format metadata to prevent redundant copies
|
||||
* @note The equality operators **do not** compare equality for pointers but for the underlying formats while considering nullability
|
||||
*/
|
||||
class Format {
|
||||
private:
|
||||
@ -133,6 +134,14 @@ namespace skyline::gpu {
|
||||
return *base;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const Format &format) const {
|
||||
return base && format.base ? (*base) == (*format.base) : base == format.base;
|
||||
}
|
||||
|
||||
constexpr bool operator!=(const Format &format) const {
|
||||
return base && format.base ? (*base) != (*format.base) : base != format.base;
|
||||
}
|
||||
|
||||
constexpr operator bool() const {
|
||||
return base;
|
||||
}
|
||||
@ -281,6 +290,10 @@ namespace skyline::gpu {
|
||||
* @return A Vulkan Image View that corresponds to the properties of this view
|
||||
*/
|
||||
vk::ImageView GetView();
|
||||
|
||||
bool operator==(const TextureView &rhs) {
|
||||
return backing == rhs.backing && type == rhs.type && format == rhs.format && mapping == rhs.mapping && range == rhs.range;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -294,11 +307,14 @@ namespace skyline::gpu {
|
||||
std::condition_variable backingCondition; //!< Signalled when a valid backing has been swapped in
|
||||
using BackingType = std::variant<vk::Image, vk::raii::Image, memory::Image>;
|
||||
BackingType backing; //!< The Vulkan image that backs this texture, it is nullable
|
||||
std::shared_ptr<FenceCycle> cycle; //!< A fence cycle for when any host operation mutating the texture has completed, it must be waited on prior to any mutations to the backing
|
||||
|
||||
std::vector<std::pair<vk::ImageViewCreateInfo, vk::raii::ImageView>> views; //!< VkImageView(s) that have been constructed from this Texture, utilized for caching
|
||||
|
||||
friend TextureManager;
|
||||
friend TextureView;
|
||||
|
||||
public:
|
||||
std::shared_ptr<FenceCycle> cycle; //!< A fence cycle for when any host operation mutating the texture has completed, it must be waited on prior to any mutations to the backing
|
||||
std::optional<GuestTexture> guest;
|
||||
texture::Dimensions dimensions;
|
||||
texture::Format format;
|
||||
|
@ -171,9 +171,9 @@ namespace skyline::nce {
|
||||
/* Replace Skyline TLS with host TLS */
|
||||
*patch++ = 0xD53BD041; // MRS X1, TPIDR_EL0
|
||||
*patch++ = 0xF9415022; // LDR X2, [X1, #0x2A0] (ThreadContext::hostTpidrEl0)
|
||||
*patch++ = 0xD51BD042; // MSR TPIDR_EL0, X2
|
||||
|
||||
/* Replace guest stack with host stack */
|
||||
*patch++ = 0xD51BD042; // MSR TPIDR_EL0, X2
|
||||
*patch++ = 0x910003E2; // MOV X2, SP
|
||||
*patch++ = 0xF9415423; // LDR X3, [X1, #0x2A8] (ThreadContext::hostSp)
|
||||
*patch++ = 0x9100007F; // MOV SP, X3
|
||||
|
Loading…
Reference in New Issue
Block a user