mirror of
https://github.com/Takiiiiiiii/strato.git
synced 2025-07-17 08:46:39 +00:00
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:
@ -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,
|
||||
})};
|
||||
|
@ -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
|
||||
|
@ -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{
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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{
|
||||
|
Reference in New Issue
Block a user