mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-06-02 03:58:46 +02:00
202 lines
8.4 KiB
C++
202 lines
8.4 KiB
C++
// SPDX-License-Identifier: MPL-2.0
|
|
// Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
|
|
|
|
#pragma once
|
|
|
|
#include <common.h>
|
|
#include <vulkan/vulkan.hpp>
|
|
|
|
namespace skyline {
|
|
namespace service::hosbinder {
|
|
class GraphicBufferProducer;
|
|
}
|
|
namespace gpu {
|
|
namespace texture {
|
|
struct Dimensions {
|
|
u32 width;
|
|
u32 height;
|
|
u32 depth;
|
|
|
|
constexpr Dimensions() : width(0), height(0), depth(0) {}
|
|
|
|
constexpr Dimensions(u32 width, u32 height) : width(width), height(height), depth(1) {}
|
|
|
|
constexpr Dimensions(u32 width, u32 height, u32 depth) : width(width), height(height), depth(depth) {}
|
|
|
|
constexpr bool operator==(const Dimensions &dimensions) {
|
|
return (width == dimensions.width) && (height == dimensions.height) && (depth == dimensions.depth);
|
|
}
|
|
|
|
constexpr bool operator!=(const Dimensions &dimensions) {
|
|
return (width != dimensions.width) || (height != dimensions.height) || (depth != dimensions.depth);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @note Blocks refers to the atomic unit of a compressed format (IE: The minimum amount of data that can be decompressed)
|
|
*/
|
|
struct Format {
|
|
u8 bpb; //!< Bytes Per Block, this is used instead of bytes per pixel as that might not be a whole number for compressed formats
|
|
u16 blockHeight; //!< The height of a block in pixels
|
|
u16 blockWidth; //!< The width of a block in pixels
|
|
vk::Format vkFormat;
|
|
|
|
constexpr bool IsCompressed() {
|
|
return (blockHeight != 1) || (blockWidth != 1);
|
|
}
|
|
|
|
/**
|
|
* @param width The width of the texture in pixels
|
|
* @param height The height of the texture in pixels
|
|
* @param depth The depth of the texture in layers
|
|
* @return The size of the texture in bytes
|
|
*/
|
|
constexpr size_t GetSize(u32 width, u32 height, u32 depth = 1) {
|
|
return (((width / blockWidth) * (height / blockHeight)) * bpb) * depth;
|
|
}
|
|
|
|
constexpr size_t GetSize(Dimensions dimensions) {
|
|
return GetSize(dimensions.width, dimensions.height, dimensions.depth);
|
|
}
|
|
|
|
constexpr bool operator==(const Format &format) {
|
|
return vkFormat == format.vkFormat;
|
|
}
|
|
|
|
constexpr bool operator!=(const Format &format) {
|
|
return vkFormat != format.vkFormat;
|
|
}
|
|
|
|
/**
|
|
* @return If this format is actually valid or not
|
|
*/
|
|
constexpr operator bool() {
|
|
return bpb;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @brief The linearity of a texture, refer to Chapter 20.1 of the Tegra X1 TRM for information
|
|
*/
|
|
enum class TileMode {
|
|
Linear, //!< This is a purely linear texture
|
|
Pitch, //!< This is a pitch-linear texture
|
|
Block, //!< This is a 16Bx2 block-linear texture
|
|
};
|
|
|
|
/**
|
|
* @brief The parameters of the tiling mode, covered in Table 76 in the Tegra X1 TRM
|
|
*/
|
|
union TileConfig {
|
|
struct {
|
|
u8 blockHeight; //!< The height of the blocks in GOBs
|
|
u8 blockDepth; //!< The depth of the blocks in GOBs
|
|
u16 surfaceWidth; //!< The width of a surface in samples
|
|
};
|
|
u32 pitch; //!< The pitch of the texture if it's pitch linear
|
|
};
|
|
|
|
enum class SwizzleChannel {
|
|
Zero, //!< Write 0 to the channel
|
|
One, //!< Write 1 to the channel
|
|
Red, //!< Red color channel
|
|
Green, //!< Green color channel
|
|
Blue, //!< Blue color channel
|
|
Alpha, //!< Alpha channel
|
|
};
|
|
|
|
struct Swizzle {
|
|
SwizzleChannel red{SwizzleChannel::Red}; //!< Swizzle for the red channel
|
|
SwizzleChannel green{SwizzleChannel::Green}; //!< Swizzle for the green channel
|
|
SwizzleChannel blue{SwizzleChannel::Blue}; //!< Swizzle for the blue channel
|
|
SwizzleChannel alpha{SwizzleChannel::Alpha}; //!< Swizzle for the alpha channel
|
|
};
|
|
}
|
|
|
|
class Texture;
|
|
|
|
/**
|
|
* @brief A texture present in guest memory, it can be used to create a corresponding Texture object for usage on the host
|
|
*/
|
|
class GuestTexture : public std::enable_shared_from_this<GuestTexture> {
|
|
private:
|
|
const DeviceState &state;
|
|
|
|
public:
|
|
u8 *pointer; //!< The address of the texture in guest memory
|
|
std::weak_ptr<Texture> host; //!< A host texture (if any) that was created from this guest texture
|
|
texture::Dimensions dimensions;
|
|
texture::Format format;
|
|
texture::TileMode tileMode;
|
|
texture::TileConfig tileConfig;
|
|
|
|
GuestTexture(const DeviceState &state, u8 *pointer, texture::Dimensions dimensions, texture::Format format, texture::TileMode tileMode = texture::TileMode::Linear, texture::TileConfig tileConfig = {});
|
|
|
|
constexpr size_t Size() {
|
|
return format.GetSize(dimensions);
|
|
}
|
|
|
|
/**
|
|
* @brief Creates a corresponding host texture object for this guest texture
|
|
* @param format The format of the host texture (Defaults to the format of the guest texture)
|
|
* @param dimensions The dimensions of the host texture (Defaults to the dimensions of the host texture)
|
|
* @param swizzle The channel swizzle of the host texture (Defaults to no channel swizzling)
|
|
* @return A shared pointer to the host texture object
|
|
* @note There can only be one host texture for a corresponding guest texture
|
|
*/
|
|
std::shared_ptr<Texture> InitializeTexture(std::optional<texture::Format> format = std::nullopt, std::optional<texture::Dimensions> dimensions = std::nullopt, texture::Swizzle swizzle = {});
|
|
};
|
|
|
|
/**
|
|
* @brief A texture which is backed by host constructs while being synchronized with the underlying guest texture
|
|
*/
|
|
class Texture {
|
|
private:
|
|
const DeviceState &state;
|
|
|
|
public:
|
|
std::vector<u8> backing; //!< The object that holds a host copy of the guest texture (Will be replaced with a vk::Image)
|
|
std::shared_ptr<GuestTexture> guest; //!< The guest texture from which this was created, it is required for syncing
|
|
texture::Dimensions dimensions;
|
|
texture::Format format;
|
|
texture::Swizzle swizzle;
|
|
|
|
public:
|
|
Texture(const DeviceState &state, std::shared_ptr<GuestTexture> guest, texture::Dimensions dimensions, texture::Format format, texture::Swizzle swizzle);
|
|
|
|
public:
|
|
/**
|
|
* @brief Convert this texture to the specified tiling mode
|
|
* @param tileMode The tiling mode to convert it to
|
|
* @param tileConfig The configuration for the tiling mode (Can be default argument for Linear)
|
|
*/
|
|
void ConvertTileMode(texture::TileMode tileMode, texture::TileConfig tileConfig = {});
|
|
|
|
/**
|
|
* @brief Converts the texture dimensions to the specified ones (As long as they are within the GuestTexture's range)
|
|
*/
|
|
void SetDimensions(texture::Dimensions dimensions);
|
|
|
|
/**
|
|
* @brief Converts the texture to have the specified format
|
|
*/
|
|
void SetFormat(texture::Format format);
|
|
|
|
/**
|
|
* @brief Change the texture channel swizzle to the specified one
|
|
*/
|
|
void SetSwizzle(texture::Swizzle swizzle);
|
|
|
|
/**
|
|
* @brief Synchronizes the host texture with the guest after it has been modified
|
|
*/
|
|
void SynchronizeHost();
|
|
|
|
/**
|
|
* @brief Synchronizes the guest texture with the host texture after it has been modified
|
|
*/
|
|
void SynchronizeGuest();
|
|
};
|
|
}
|
|
}
|