From 2a8bcc60c7f47ad36cd173343c45426ef6f6be3b Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Wed, 8 Dec 2021 00:43:39 +0530 Subject: [PATCH] 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. --- .../gpu/interconnect/graphics_context.h | 129 +++++++++++------- .../skyline/soc/gm20b/engines/maxwell/types.h | 38 +++--- .../skyline/soc/gm20b/engines/maxwell_3d.cpp | 18 +-- .../skyline/soc/gm20b/engines/maxwell_3d.h | 2 +- 4 files changed, 108 insertions(+), 79 deletions(-) diff --git a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h index 53e490df..1615ba55 100644 --- a/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h +++ b/app/src/main/cpp/skyline/gpu/interconnect/graphics_context.h @@ -88,26 +88,31 @@ namespace skyline::gpu::interconnect { } }; - std::array renderTargets{}; //!< The target textures to render into as color attachments + std::array 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(format)); + throw exception("Cannot translate the supplied color RT format: 0x{:X}", static_cast(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::max()) throw exception("Base array layer ({}) exceeds the range of array count ({}) (with layer count = {})", baseArrayLayer, std::numeric_limits::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 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); diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h index 734f3911..28eae46a 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell/types.h @@ -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 diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp index 6e67f87e..d3234066 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.cpp @@ -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) diff --git a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h index 87782a5a..39c4d082 100644 --- a/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h +++ b/app/src/main/cpp/skyline/soc/gm20b/engines/maxwell_3d.h @@ -68,7 +68,7 @@ namespace skyline::soc::gm20b::engine::maxwell3d { Register<0xB2, type::SyncpointAction> syncpointAction; Register<0xDF, u32> rasterizerEnable; - Register<0x200, std::array> renderTargets; + Register<0x200, std::array> renderTargets; Register<0x280, std::array> viewportTransforms; Register<0x300, std::array> viewports;