Make Render Targets Abstract for Color/Depth RTs

This prefixes all RT functions that deal with color RTs with `Color` and abstracts out common functions that will be used for both color and depth RTs. All common Maxwell3D structures are also moved out of the `ColorRenderTarget` (`RenderTarget` previously) structure.
This commit is contained in:
PixelyIon 2021-12-08 00:43:39 +05:30
parent b0f084ae32
commit 2a8bcc60c7
4 changed files with 108 additions and 79 deletions

View File

@ -88,26 +88,31 @@ namespace skyline::gpu::interconnect {
}
};
std::array<RenderTarget, maxwell3d::RenderTargetCount> renderTargets{}; //!< The target textures to render into as color attachments
std::array<RenderTarget, maxwell3d::RenderTargetCount> colorRenderTargets{}; //!< The target textures to render into as color attachments
maxwell3d::RenderTargetControl renderTargetControl{};
public:
void SetRenderTargetAddressHigh(size_t index, u32 high) {
auto &renderTarget{renderTargets.at(index)};
void SetRenderTargetAddressHigh(RenderTarget &renderTarget, u32 high) {
renderTarget.iova.high = high;
renderTarget.guest.mappings.clear();
renderTarget.view.reset();
}
void SetRenderTargetAddressLow(size_t index, u32 low) {
auto &renderTarget{renderTargets.at(index)};
void SetColorRenderTargetAddressHigh(size_t index, u32 high) {
SetRenderTargetAddressHigh(colorRenderTargets.at(index), high);
}
void SetRenderTargetAddressLow(RenderTarget &renderTarget, u32 low) {
renderTarget.iova.low = low;
renderTarget.guest.mappings.clear();
renderTarget.view.reset();
}
void SetRenderTargetWidth(size_t index, u32 value) {
auto &renderTarget{renderTargets.at(index)};
void SetColorRenderTargetAddressLow(size_t index, u32 low) {
SetRenderTargetAddressLow(colorRenderTargets.at(index), low);
}
void SetRenderTargetWidth(RenderTarget &renderTarget, u32 value) {
renderTarget.widthBytes = value;
if (renderTarget.guest.tileConfig.mode == texture::TileMode::Linear && renderTarget.guest.format)
value /= renderTarget.guest.format->bpb; // Width is in bytes rather than format units for linear textures
@ -115,74 +120,82 @@ namespace skyline::gpu::interconnect {
renderTarget.view.reset();
}
void SetRenderTargetHeight(size_t index, u32 value) {
auto &renderTarget{renderTargets.at(index)};
void SetColorRenderTargetWidth(size_t index, u32 value) {
SetRenderTargetWidth(colorRenderTargets.at(index), value);
}
void SetRenderTargetHeight(RenderTarget &renderTarget, u32 value) {
renderTarget.guest.dimensions.height = value;
renderTarget.view.reset();
}
void SetRenderTargetFormat(size_t index, maxwell3d::RenderTarget::ColorFormat format) {
auto &renderTarget{renderTargets.at(index)};
void SetColorRenderTargetHeight(size_t index, u32 value) {
SetRenderTargetHeight(colorRenderTargets.at(index), value);
}
void SetColorRenderTargetFormat(size_t index, maxwell3d::ColorRenderTarget::Format format) {
auto &renderTarget{colorRenderTargets.at(index)};
renderTarget.guest.format = [&]() -> texture::Format {
using MaxwellColorRtFormat = maxwell3d::ColorRenderTarget::Format;
switch (format) {
case maxwell3d::RenderTarget::ColorFormat::None:
case MaxwellColorRtFormat::None:
return {};
case maxwell3d::RenderTarget::ColorFormat::R32B32G32A32Float:
case MaxwellColorRtFormat::R32B32G32A32Float:
return format::R32B32G32A32Float;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Unorm:
case MaxwellColorRtFormat::R16G16B16A16Unorm:
return format::R16G16B16A16Unorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Snorm:
case MaxwellColorRtFormat::R16G16B16A16Snorm:
return format::R16G16B16A16Snorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Sint:
case MaxwellColorRtFormat::R16G16B16A16Sint:
return format::R16G16B16A16Sint;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Uint:
case MaxwellColorRtFormat::R16G16B16A16Uint:
return format::R16G16B16A16Uint;
case maxwell3d::RenderTarget::ColorFormat::R16G16B16A16Float:
case MaxwellColorRtFormat::R16G16B16A16Float:
return format::R16G16B16A16Float;
case maxwell3d::RenderTarget::ColorFormat::B8G8R8A8Unorm:
case MaxwellColorRtFormat::B8G8R8A8Unorm:
return format::B8G8R8A8Unorm;
case maxwell3d::RenderTarget::ColorFormat::B8G8R8A8Srgb:
case MaxwellColorRtFormat::B8G8R8A8Srgb:
return format::B8G8R8A8Srgb;
case maxwell3d::RenderTarget::ColorFormat::A2B10G10R10Unorm:
case MaxwellColorRtFormat::A2B10G10R10Unorm:
return format::A2B10G10R10Unorm;
case maxwell3d::RenderTarget::ColorFormat::R8G8B8A8Unorm:
case MaxwellColorRtFormat::R8G8B8A8Unorm:
return format::R8G8B8A8Unorm;
case maxwell3d::RenderTarget::ColorFormat::A8B8G8R8Srgb:
case MaxwellColorRtFormat::A8B8G8R8Srgb:
return format::A8B8G8R8Srgb;
case maxwell3d::RenderTarget::ColorFormat::A8B8G8R8Snorm:
case MaxwellColorRtFormat::A8B8G8R8Snorm:
return format::A8B8G8R8Snorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16Unorm:
case MaxwellColorRtFormat::R16G16Unorm:
return format::R16G16Unorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16Snorm:
case MaxwellColorRtFormat::R16G16Snorm:
return format::R16G16Snorm;
case maxwell3d::RenderTarget::ColorFormat::R16G16Sint:
case MaxwellColorRtFormat::R16G16Sint:
return format::R16G16Sint;
case maxwell3d::RenderTarget::ColorFormat::R16G16Uint:
case MaxwellColorRtFormat::R16G16Uint:
return format::R16G16Uint;
case maxwell3d::RenderTarget::ColorFormat::R16G16Float:
case MaxwellColorRtFormat::R16G16Float:
return format::R16G16Float;
case maxwell3d::RenderTarget::ColorFormat::B10G11R11Float:
case MaxwellColorRtFormat::B10G11R11Float:
return format::B10G11R11Float;
case maxwell3d::RenderTarget::ColorFormat::R32Float:
case MaxwellColorRtFormat::R32Float:
return format::R32Float;
case maxwell3d::RenderTarget::ColorFormat::R8G8Unorm:
case MaxwellColorRtFormat::R8G8Unorm:
return format::R8G8Unorm;
case maxwell3d::RenderTarget::ColorFormat::R8G8Snorm:
case MaxwellColorRtFormat::R8G8Snorm:
return format::R8G8Snorm;
case maxwell3d::RenderTarget::ColorFormat::R16Unorm:
case MaxwellColorRtFormat::R16Unorm:
return format::R16Unorm;
case maxwell3d::RenderTarget::ColorFormat::R16Float:
case MaxwellColorRtFormat::R16Float:
return format::R16Float;
case maxwell3d::RenderTarget::ColorFormat::R8Unorm:
case MaxwellColorRtFormat::R8Unorm:
return format::R8Unorm;
case maxwell3d::RenderTarget::ColorFormat::R8Snorm:
case MaxwellColorRtFormat::R8Snorm:
return format::R8Snorm;
case maxwell3d::RenderTarget::ColorFormat::R8Sint:
case MaxwellColorRtFormat::R8Sint:
return format::R8Sint;
case maxwell3d::RenderTarget::ColorFormat::R8Uint:
case MaxwellColorRtFormat::R8Uint:
return format::R8Uint;
default:
throw exception("Cannot translate the supplied RT format: 0x{:X}", static_cast<u32>(format));
throw exception("Cannot translate the supplied color RT format: 0x{:X}", static_cast<u32>(format));
}
}();
@ -193,8 +206,7 @@ namespace skyline::gpu::interconnect {
renderTarget.view.reset();
}
void SetRenderTargetTileMode(size_t index, maxwell3d::RenderTarget::TileMode mode) {
auto &renderTarget{renderTargets.at(index)};
void SetRenderTargetTileMode(RenderTarget &renderTarget, maxwell3d::RenderTargetTileMode mode) {
auto &config{renderTarget.guest.tileConfig};
if (mode.isLinear) {
if (config.mode != texture::TileMode::Linear && renderTarget.guest.format) {
@ -217,22 +229,32 @@ namespace skyline::gpu::interconnect {
renderTarget.view.reset();
}
void SetRenderTargetArrayMode(size_t index, maxwell3d::RenderTarget::ArrayMode mode) {
auto &renderTarget{renderTargets.at(index)};
void SetColorRenderTargetTileMode(size_t index, maxwell3d::RenderTargetTileMode mode) {
SetRenderTargetTileMode(colorRenderTargets.at(index), mode);
}
void SetRenderTargetArrayMode(RenderTarget &renderTarget, maxwell3d::RenderTargetArrayMode mode) {
renderTarget.guest.layerCount = mode.layerCount;
if (mode.volume)
throw exception("RT Array Volumes are not supported (with layer count = {})", mode.layerCount);
renderTarget.view.reset();
}
void SetRenderTargetLayerStride(size_t index, u32 layerStrideLsr2) {
auto &renderTarget{renderTargets.at(index)};
void SetColorRenderTargetArrayMode(size_t index, maxwell3d::RenderTargetArrayMode mode) {
SetRenderTargetArrayMode(colorRenderTargets.at(index), mode);
}
void SetRenderTargetLayerStride(RenderTarget &renderTarget, u32 layerStrideLsr2) {
renderTarget.guest.layerStride = layerStrideLsr2 << 2;
renderTarget.view.reset();
}
void SetRenderTargetBaseLayer(size_t index, u32 baseArrayLayer) {
auto &renderTarget{renderTargets.at(index)};
void SetColorRenderTargetLayerStride(size_t index, u32 layerStrideLsr2) {
SetRenderTargetLayerStride(colorRenderTargets.at(index), layerStrideLsr2);
}
void SetColorRenderTargetBaseLayer(size_t index, u32 baseArrayLayer) {
auto &renderTarget{colorRenderTargets.at(index)};
if (baseArrayLayer > std::numeric_limits<u16>::max())
throw exception("Base array layer ({}) exceeds the range of array count ({}) (with layer count = {})", baseArrayLayer, std::numeric_limits<u16>::max(), renderTarget.guest.layerCount);
@ -240,8 +262,7 @@ namespace skyline::gpu::interconnect {
renderTarget.view.reset();
}
TextureView *GetRenderTarget(size_t index) {
auto &renderTarget{renderTargets.at(index)};
TextureView *GetRenderTarget(RenderTarget& renderTarget) {
if (renderTarget.disabled)
return nullptr;
else if (renderTarget.view)
@ -259,6 +280,10 @@ namespace skyline::gpu::interconnect {
return renderTarget.view.get();
}
TextureView *GetColorRenderTarget(size_t index) {
return GetRenderTarget(colorRenderTargets.at(index));
}
void UpdateRenderTargetControl(maxwell3d::RenderTargetControl control) {
renderTargetControl = control;
}
@ -333,7 +358,7 @@ namespace skyline::gpu::interconnect {
void ClearBuffers(maxwell3d::ClearBuffers clear) {
auto renderTargetIndex{renderTargetControl[clear.renderTargetId]};
auto renderTarget{GetRenderTarget(renderTargetIndex)};
auto renderTarget{GetColorRenderTarget(renderTargetIndex)};
if (renderTarget) {
std::lock_guard lock(*renderTarget->texture);
@ -1141,7 +1166,7 @@ namespace skyline::gpu::interconnect {
std::vector<TextureView *> activeRenderTargets;
for (u32 index{}; index < maxwell3d::RenderTargetCount; index++) {
auto renderTarget{GetRenderTarget(index)};
auto renderTarget{GetColorRenderTarget(index)};
if (renderTarget) {
renderTargetLocks.emplace_back(*renderTarget);
activeRenderTargets.push_back(renderTarget);

View File

@ -42,16 +42,32 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
constexpr static size_t RenderTargetCount{8}; //!< Maximum amount of render targets that can be bound at once on Maxwell 3D
struct RenderTargetTileMode {
u8 blockWidthLog2 : 4; //!< The width of a block in GOBs with log2 encoding, this is always assumed to be 1 as it is the only configuration the X1 supports
u8 blockHeightLog2 : 4; //!< The height of a block in GOBs with log2 encoding
u8 blockDepthLog2 : 4; //!< The depth of a block in GOBs with log2 encoding
bool isLinear : 1;
u8 _pad0_ : 3;
bool is3d : 1;
u16 _pad1_ : 15;
};
struct RenderTargetArrayMode {
u16 layerCount;
bool volume : 1;
u16 _pad_ : 15;
};
/**
* @brief The target image's metadata for any rendering operations
* @note Any render target with ColorFormat::None as their format are effectively disabled
*/
struct RenderTarget {
struct ColorRenderTarget {
Address address;
u32 width;
u32 height;
enum class ColorFormat : u32 {
enum class Format : u32 {
None = 0x0,
R32B32G32A32Float = 0xC0,
R16G16B16A16Unorm = 0xC6,
@ -82,27 +98,15 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
R8Uint = 0xF6,
} format;
struct TileMode {
u8 blockWidthLog2 : 4; //!< The width of a block in GOBs with log2 encoding, this is always assumed to be 1 as it is the only configuration the X1 supports
u8 blockHeightLog2 : 4; //!< The height of a block in GOBs with log2 encoding
u8 blockDepthLog2 : 4; //!< The depth of a block in GOBs with log2 encoding
bool isLinear : 1;
u8 _pad0_ : 3;
bool is3d : 1;
u16 _pad1_ : 15;
} tileMode;
RenderTargetTileMode tileMode;
struct ArrayMode {
u16 layerCount;
bool volume : 1;
u16 _pad_ : 15;
} arrayMode;
RenderTargetArrayMode arrayMode;
u32 layerStrideLsr2; //!< The length of the stride of a layer shifted right by 2 bits
u32 baseLayer;
u32 _pad_[0x7];
};
static_assert(sizeof(RenderTarget) == (0x10 * sizeof(u32)));
static_assert(sizeof(ColorRenderTarget) == (0x10 * sizeof(u32)));
constexpr static size_t ViewportCount{16}; //!< Amount of viewports on Maxwell 3D, array size for any per-viewport parameter such as transform, scissors, etc

View File

@ -84,31 +84,31 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
#define RENDER_TARGET_ARRAY(z, index, data) \
MAXWELL3D_ARRAY_STRUCT_STRUCT_CASE(renderTargets, index, address, high, { \
context.SetRenderTargetAddressHigh(index, high); \
context.SetColorRenderTargetAddressHigh(index, high); \
}) \
MAXWELL3D_ARRAY_STRUCT_STRUCT_CASE(renderTargets, index, address, low, { \
context.SetRenderTargetAddressLow(index, low); \
context.SetColorRenderTargetAddressLow(index, low); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(renderTargets, index, width, { \
context.SetRenderTargetWidth(index, width); \
context.SetColorRenderTargetWidth(index, width); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(renderTargets, index, height, { \
context.SetRenderTargetHeight(index, height); \
context.SetColorRenderTargetHeight(index, height); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(renderTargets, index, format, { \
context.SetRenderTargetFormat(index, format); \
context.SetColorRenderTargetFormat(index, format); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(renderTargets, index, tileMode, { \
context.SetRenderTargetTileMode(index, tileMode); \
context.SetColorRenderTargetTileMode(index, tileMode); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(renderTargets, index, arrayMode, { \
context.SetRenderTargetArrayMode(index, arrayMode); \
context.SetColorRenderTargetArrayMode(index, arrayMode); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(renderTargets, index, layerStrideLsr2, { \
context.SetRenderTargetLayerStride(index, layerStrideLsr2); \
context.SetColorRenderTargetLayerStride(index, layerStrideLsr2); \
}) \
MAXWELL3D_ARRAY_STRUCT_CASE(renderTargets, index, baseLayer, { \
context.SetRenderTargetBaseLayer(index, baseLayer); \
context.SetColorRenderTargetBaseLayer(index, baseLayer); \
})
BOOST_PP_REPEAT(8, RENDER_TARGET_ARRAY, 0)

View File

@ -68,7 +68,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0xB2, type::SyncpointAction> syncpointAction;
Register<0xDF, u32> rasterizerEnable;
Register<0x200, std::array<type::RenderTarget, type::RenderTargetCount>> renderTargets;
Register<0x200, std::array<type::ColorRenderTarget, type::RenderTargetCount>> renderTargets;
Register<0x280, std::array<type::ViewportTransform, type::ViewportCount>> viewportTransforms;
Register<0x300, std::array<type::Viewport, type::ViewportCount>> viewports;