Improve Shared Fonts + Fix AM PopLaunchParameter & Choreographer Bug

* Move Shared Font TTFs to AAsset storage + Support external shared font loading from `/data/data/skyline.emu/data/fonts`
* Fix bug in `IApplicationFunctions::PopLaunchParameter` caused by ignoring `LaunchParameterKind`
* Fix bug with Choreographer causing it to be awoken and exit prior to the destruction of `PresentationEngine`
* Fix bug with `IDirectory::Read` where it used `inputBuf` for the output buffer rather than `outputBuf`
* Improve `GetFunctionStackTrace` logs when `dli_sname` or `dli_fname` are missing
* Support more RT Formats
This commit is contained in:
PixelyIon
2021-09-30 20:42:30 +05:30
committed by Billy Laws
parent 95a08627e5
commit f8acc1e131
38 changed files with 228 additions and 155 deletions

View File

@ -28,7 +28,7 @@ namespace skyline::gpu::interconnect {
nodes.emplace_back(std::in_place_type_t<node::NextSubpassNode>(), function);
}
void CommandExecutor::AddClearSubpass(TextureView attachment, const vk::ClearColorValue &value) {
void CommandExecutor::AddClearColorSubpass(TextureView attachment, const vk::ClearColorValue &value) {
bool newRenderpass{CreateRenderpass(vk::Rect2D{
.extent = attachment.backing->dimensions,
})};

View File

@ -35,7 +35,7 @@ namespace skyline::gpu::interconnect {
* @brief Adds a subpass that clears the entirety of the specified attachment with a value, it may utilize VK_ATTACHMENT_LOAD_OP_CLEAR for a more efficient clear when possible
* @note Any texture supplied to this **must** be locked by the calling thread, it should also undergo no persistent layout transitions till execution
*/
void AddClearSubpass(TextureView attachment, const vk::ClearColorValue& value);
void AddClearColorSubpass(TextureView attachment, const vk::ClearColorValue& value);
/**
* @brief Execute all the nodes and submit the resulting command buffer to the GPU

View File

@ -22,7 +22,7 @@ namespace skyline::gpu::interconnect {
gpu::interconnect::CommandExecutor &executor;
struct RenderTarget {
bool disabled{}; //!< If this RT has been disabled and will be an unbound attachment instead
bool disabled{true}; //!< If this RT has been disabled and will be an unbound attachment instead
union {
u64 gpuAddress;
struct {
@ -90,6 +90,10 @@ namespace skyline::gpu::interconnect {
return {};
case maxwell3d::RenderTarget::ColorFormat::R32B32G32A32Float:
return format::R32B32G32A32Float;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Unorm:
return format::R16G16B16A16Unorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Uint:
return format::R16G16B16A16Uint;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Float:
return format::R16G16B16A16Float;
case maxwell3d::RenderTarget::ColorFormat::A2B10G10R10Unorm:
@ -98,6 +102,8 @@ namespace skyline::gpu::interconnect {
return format::R8G8B8A8Unorm;
case maxwell3d::RenderTarget::ColorFormat::A8B8G8R8Srgb:
return format::A8B8G8R8Srgb;
case maxwell3d::RenderTarget::ColorFormat::A8B8G8R8Snorm:
return format::A8B8G8R8Snorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16Snorm:
return format::R16G16Snorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16Float:
@ -106,8 +112,12 @@ namespace skyline::gpu::interconnect {
return format::B10G11R11Float;
case maxwell3d::RenderTarget::ColorFormat::R32Float:
return format::R32Float;
case maxwell3d::RenderTarget::ColorFormat::R8G8Unorm:
return format::R8G8Unorm;
case maxwell3d::RenderTarget::ColorFormat::R8G8Snorm:
return format::R8G8Snorm;
case maxwell3d::RenderTarget::ColorFormat::R16Unorm:
return format::R16Unorm;
case maxwell3d::RenderTarget::ColorFormat::R16Float:
return format::R16Float;
case maxwell3d::RenderTarget::ColorFormat::R8Unorm:
@ -234,8 +244,8 @@ namespace skyline::gpu::interconnect {
if (scissor.extent.width == 0 || scissor.extent.height == 0)
return;
if (scissor.extent.width == renderTarget.backing->dimensions.width && scissor.extent.width == renderTarget.backing->dimensions.width && renderTarget.range.baseArrayLayer == 0 && renderTarget.range.layerCount == 1 && clear.layerId == 0) {
executor.AddClearSubpass(renderTarget, clearColorValue);
if (scissor.extent.width == renderTarget.backing->dimensions.width && scissor.extent.height == renderTarget.backing->dimensions.height && renderTarget.range.baseArrayLayer == 0 && renderTarget.range.layerCount == 1 && clear.layerId == 0) {
executor.AddClearColorSubpass(renderTarget, clearColorValue);
} else {
executor.AddSubpass([aspect, clearColorValue = clearColorValue, layerId = clear.layerId, scissor](vk::raii::CommandBuffer &commandBuffer, const std::shared_ptr<FenceCycle> &, GPU &) {
commandBuffer.clearAttachments(vk::ClearAttachment{

View File

@ -32,8 +32,10 @@ namespace skyline::gpu {
env->DeleteGlobalRef(jSurface);
if (choreographerThread.joinable()) {
if (choreographerLooper)
if (choreographerLooper) {
choreographerStop = true;
ALooper_wake(choreographerLooper);
}
choreographerThread.join();
}
}
@ -62,7 +64,7 @@ namespace skyline::gpu {
signal::SetSignalHandler({SIGINT, SIGILL, SIGTRAP, SIGBUS, SIGFPE, SIGSEGV}, signal::ExceptionalSignalHandler);
choreographerLooper = ALooper_prepare(0);
AChoreographer_postFrameCallback64(AChoreographer_getInstance(), reinterpret_cast<AChoreographer_frameCallback64>(&ChoreographerCallback), this);
ALooper_pollAll(-1, nullptr, nullptr, nullptr); // Will block and process callbacks till ALooper_wake() is called
while (ALooper_pollAll(-1, nullptr, nullptr, nullptr) == ALOOPER_POLL_WAKE && !choreographerStop); // Will block and process callbacks till ALooper_wake() is called with choreographerStop set
} catch (const signal::SignalException &e) {
state.logger->Error("{}\nStack Trace:{}", e.what(), state.loader->GetStackTrace(e.frames));
if (state.process)
@ -275,9 +277,8 @@ namespace skyline::gpu {
// We need to nullify the timestamp if it transitioned from being specified (non-zero) to unspecified (zero)
timestamp = NativeWindowTimestampAuto;
if (timestamp)
if (window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP, timestamp))
throw exception("Setting the buffer timestamp to {} failed with {}", timestamp, result);
if (timestamp && (result = window->perform(window, NATIVE_WINDOW_SET_BUFFERS_TIMESTAMP, timestamp)))
throw exception("Setting the buffer timestamp to {} failed with {}", timestamp, result);
if ((result = window->perform(window, NATIVE_WINDOW_GET_NEXT_FRAME_ID, &frameId)))
throw exception("Retrieving the next frame's ID failed with {}", result);

View File

@ -49,6 +49,7 @@ namespace skyline::gpu {
ALooper *choreographerLooper{};
i64 lastChoreographerTime{}; //!< The timestamp of the last invocation of Choreographer::doFrame
i64 refreshCycleDuration{}; //!< The duration of a single refresh cycle for the display in nanoseconds
bool choreographerStop{}; //!< If the Choreographer thread should stop on the next ALooper_wake()
/**
* @url https://developer.android.com/ndk/reference/group/choreographer#achoreographer_postframecallback64

View File

@ -15,17 +15,22 @@ namespace skyline::gpu::format {
constexpr Format R5G6B5Unorm{sizeof(u16), vkf::eR5G6B5UnormPack16};
constexpr Format A2B10G10R10Unorm{sizeof(u32), vkf::eA2B10G10R10UnormPack32};
constexpr Format A8B8G8R8Srgb{sizeof(u32), vkf::eA8B8G8R8SrgbPack32};
constexpr Format A8B8G8R8Snorm{sizeof(u32), vkf::eA8B8G8R8SnormPack32};
constexpr Format R16G16Snorm{sizeof(u32), vkf::eR16G16Snorm};
constexpr Format R16G16Float{sizeof(u32), vkf::eR16G16Sfloat};
constexpr Format B10G11R11Float{sizeof(u32), vkf::eB10G11R11UfloatPack32};
constexpr Format R32Float{sizeof(u32), vkf::eR32Sfloat};
constexpr Format R8G8Unorm{sizeof(u16), vkf::eR8G8Unorm};
constexpr Format R8G8Snorm{sizeof(u16), vkf::eR8G8Snorm};
constexpr Format R16Unorm{sizeof(u16), vkf::eR16Unorm};
constexpr Format R16Float{sizeof(u16), vkf::eR16Sfloat};
constexpr Format R8Unorm{sizeof(u8), vkf::eR8Unorm};
constexpr Format R32B32G32A32Float{sizeof(u32) * 4, vkf::eR32G32B32A32Sfloat, .swizzle = {
.blue = swc::Green,
.green = swc::Blue,
}};
constexpr Format R16G16B16A16Unorm{sizeof(u16) * 4, vkf::eR16G16B16A16Unorm};
constexpr Format R16G16B16A16Uint{sizeof(u16) * 4, vkf::eR16G16B16A16Uint};
constexpr Format R16G16B16A16Float{sizeof(u16) * 4, vkf::eR16G16B16A16Sfloat};
/**
@ -41,6 +46,8 @@ namespace skyline::gpu::format {
return A2B10G10R10Unorm;
case vk::Format::eA8B8G8R8SrgbPack32:
return A8B8G8R8Srgb;
case vk::Format::eA8B8G8R8SnormPack32:
return A8B8G8R8Snorm;
case vk::Format::eR16G16Snorm:
return R16G16Snorm;
case vk::Format::eR16G16Sfloat:
@ -49,12 +56,20 @@ namespace skyline::gpu::format {
return B10G11R11Float;
case vk::Format::eR32Sfloat:
return format::R32Float;
case vk::Format::eR16Unorm:
return R16Unorm;
case vk::Format::eR16Sfloat:
return R16Float;
case vk::Format::eR8G8Unorm:
return R8G8Unorm;
case vk::Format::eR8G8Snorm:
return R8G8Snorm;
case vk::Format::eR8Unorm:
return R8Unorm;
case vk::Format::eR16G16B16A16Unorm:
return R16G16B16A16Unorm;
case vk::Format::eR16G16B16A16Uint:
return R16G16B16A16Uint;
case vk::Format::eR16G16B16A16Sfloat:
return R16G16B16A16Float;
default:

View File

@ -71,11 +71,9 @@ namespace skyline::gpu {
textures.emplace(mappingEnd, TextureMapping{texture, it, guestMapping});
while ((++it) != texture->guest->mappings.end()) {
guestMapping = *it;
mappingEnd = hostMapping = std::upper_bound(textures.begin(), textures.end(), guestMapping);
while (hostMapping != textures.begin() && std::prev(hostMapping)->end() > guestMapping.begin()) {
// TODO: Delete textures not in texture pool
}
textures.emplace(mappingEnd, TextureMapping{texture, it, guestMapping});
auto mapping{std::upper_bound(textures.begin(), textures.end(), guestMapping)};
// TODO: Delete overlapping textures that aren't in texture pool
textures.emplace(mapping, TextureMapping{texture, it, guestMapping});
}
return TextureView(texture, static_cast<vk::ImageViewType>(guestTexture.type), vk::ImageSubresourceRange{