Implement Maxwell3D Depth/Stencil Render Target

Support the Maxwell3D Depth RT for Z-buffering, this just creates an equivalent `RenderTarget` object with no support on the API-user side (IE: `Draw` and `ClearBuffers`).
This commit is contained in:
PixelyIon 2021-12-08 00:42:54 +05:30
parent 2a8bcc60c7
commit 68c990c041
5 changed files with 115 additions and 3 deletions

View File

@ -91,7 +91,13 @@ namespace skyline::gpu::interconnect {
std::array<RenderTarget, maxwell3d::RenderTargetCount> colorRenderTargets{}; //!< The target textures to render into as color attachments
maxwell3d::RenderTargetControl renderTargetControl{};
RenderTarget depthRenderTarget{}; //!< The target texture to render depth/stencil into
public:
void SetDepthRenderTargetEnabled(bool enabled) {
depthRenderTarget.disabled = !enabled;
}
void SetRenderTargetAddressHigh(RenderTarget &renderTarget, u32 high) {
renderTarget.iova.high = high;
renderTarget.guest.mappings.clear();
@ -102,6 +108,10 @@ namespace skyline::gpu::interconnect {
SetRenderTargetAddressHigh(colorRenderTargets.at(index), high);
}
void SetDepthRenderTargetAddressHigh(u32 high) {
SetRenderTargetAddressHigh(depthRenderTarget, high);
}
void SetRenderTargetAddressLow(RenderTarget &renderTarget, u32 low) {
renderTarget.iova.low = low;
renderTarget.guest.mappings.clear();
@ -112,6 +122,10 @@ namespace skyline::gpu::interconnect {
SetRenderTargetAddressLow(colorRenderTargets.at(index), low);
}
void SetDepthRenderTargetAddressLow(u32 low) {
SetRenderTargetAddressLow(depthRenderTarget, low);
}
void SetRenderTargetWidth(RenderTarget &renderTarget, u32 value) {
renderTarget.widthBytes = value;
if (renderTarget.guest.tileConfig.mode == texture::TileMode::Linear && renderTarget.guest.format)
@ -124,6 +138,10 @@ namespace skyline::gpu::interconnect {
SetRenderTargetWidth(colorRenderTargets.at(index), value);
}
void SetDepthRenderTargetWidth(u32 value) {
SetRenderTargetWidth(depthRenderTarget, value);
}
void SetRenderTargetHeight(RenderTarget &renderTarget, u32 value) {
renderTarget.guest.dimensions.height = value;
renderTarget.view.reset();
@ -133,6 +151,10 @@ namespace skyline::gpu::interconnect {
SetRenderTargetHeight(colorRenderTargets.at(index), value);
}
void SetDepthRenderTargetHeight(u32 value) {
SetRenderTargetHeight(depthRenderTarget, value);
}
void SetColorRenderTargetFormat(size_t index, maxwell3d::ColorRenderTarget::Format format) {
auto &renderTarget{colorRenderTargets.at(index)};
renderTarget.guest.format = [&]() -> texture::Format {
@ -206,6 +228,23 @@ namespace skyline::gpu::interconnect {
renderTarget.view.reset();
}
void SetDepthRenderTargetFormat(maxwell3d::DepthRtFormat format) {
depthRenderTarget.guest.format = [&]() -> texture::Format {
using MaxwellDepthRtFormat = maxwell3d::DepthRtFormat;
switch (format) {
case MaxwellDepthRtFormat::S8D24Unorm:
return format::S8D24Unorm;
default:
throw exception("Cannot translate the supplied depth RT format: 0x{:X}", static_cast<u32>(format));
}
}();
if (depthRenderTarget.guest.tileConfig.mode == texture::TileMode::Linear && depthRenderTarget.guest.format)
depthRenderTarget.guest.dimensions.width = depthRenderTarget.widthBytes / depthRenderTarget.guest.format->bpb;
depthRenderTarget.view.reset();
}
void SetRenderTargetTileMode(RenderTarget &renderTarget, maxwell3d::RenderTargetTileMode mode) {
auto &config{renderTarget.guest.tileConfig};
if (mode.isLinear) {
@ -233,17 +272,25 @@ namespace skyline::gpu::interconnect {
SetRenderTargetTileMode(colorRenderTargets.at(index), mode);
}
void SetDepthRenderTargetTileMode(maxwell3d::RenderTargetTileMode mode) {
SetRenderTargetTileMode(depthRenderTarget, 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 SetColorRenderTargetArrayMode(size_t index, maxwell3d::RenderTargetArrayMode mode) {
if (mode.volume)
throw exception("Color RT Array Volumes are not supported (with layer count = {})", mode.layerCount);
SetRenderTargetArrayMode(colorRenderTargets.at(index), mode);
}
void SetDepthRenderTargetArrayMode(maxwell3d::RenderTargetArrayMode mode) {
SetRenderTargetArrayMode(depthRenderTarget, mode);
}
void SetRenderTargetLayerStride(RenderTarget &renderTarget, u32 layerStrideLsr2) {
renderTarget.guest.layerStride = layerStrideLsr2 << 2;
renderTarget.view.reset();
@ -253,6 +300,10 @@ namespace skyline::gpu::interconnect {
SetRenderTargetLayerStride(colorRenderTargets.at(index), layerStrideLsr2);
}
void SetDepthRenderTargetLayerStride(u32 layerStrideLsr2) {
SetRenderTargetLayerStride(depthRenderTarget, layerStrideLsr2);
}
void SetColorRenderTargetBaseLayer(size_t index, u32 baseArrayLayer) {
auto &renderTarget{colorRenderTargets.at(index)};
if (baseArrayLayer > std::numeric_limits<u16>::max())
@ -284,6 +335,10 @@ namespace skyline::gpu::interconnect {
return GetRenderTarget(colorRenderTargets.at(index));
}
TextureView *GetDepthRenderTarget() {
return GetRenderTarget(depthRenderTarget);
}
void UpdateRenderTargetControl(maxwell3d::RenderTargetControl control) {
renderTargetControl = control;
}

View File

@ -11,6 +11,7 @@ namespace skyline::gpu::format {
using vka = vk::ImageAspectFlagBits;
using swc = gpu::texture::SwizzleChannel;
// Color Formats
constexpr Format R8G8B8A8Unorm{sizeof(u32), vkf::eR8G8B8A8Unorm};
constexpr Format R5G6B5Unorm{sizeof(u16), vkf::eR5G6B5UnormPack16};
constexpr Format A2B10G10R10Unorm{sizeof(u32), vkf::eA2B10G10R10UnormPack32};
@ -42,4 +43,7 @@ namespace skyline::gpu::format {
constexpr Format R16G16B16A16Float{sizeof(u16) * 4, vkf::eR16G16B16A16Sfloat};
constexpr Format B8G8R8A8Unorm{sizeof(u32), vkf::eB8G8R8A8Unorm};
constexpr Format B8G8R8A8Srgb{sizeof(u32), vkf::eB8G8R8A8Srgb};
// Depth/Stencil Formats
constexpr Format S8D24Unorm{sizeof(u32), vkf::eD24UnormS8Uint, vka::eStencil | vka::eDepth}; // TODO: Swizzle Depth/Stencil
}

View File

@ -108,6 +108,20 @@ namespace skyline::soc::gm20b::engine::maxwell3d::type {
};
static_assert(sizeof(ColorRenderTarget) == (0x10 * sizeof(u32)));
enum class DepthRtFormat : u32 {
D32Float = 0x0A,
D16Unorm = 0x13,
S8D24Unorm = 0x14,
D24X8Unorm = 0x15,
D24S8Unorm = 0x16,
S8Uint = 0x17,
D24C8Unorm = 0x18,
D32S8X24Float = 0x19,
D24X8S8C8X16Unorm = 0x1D,
D32X8C8X16Float = 0x1E,
D32S8C8X16Float = 0x1F,
};
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

@ -115,6 +115,34 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
static_assert(type::RenderTargetCount == 8 && type::RenderTargetCount < BOOST_PP_LIMIT_REPEAT);
#undef RENDER_TARGET_ARRAY
MAXWELL3D_CASE(depthTargetEnable, {
context.SetDepthRenderTargetEnabled(depthTargetEnable);
})
MAXWELL3D_STRUCT_CASE(depthTargetAddress, high, {
context.SetDepthRenderTargetAddressHigh(high);
})
MAXWELL3D_STRUCT_CASE(depthTargetAddress, low, {
context.SetDepthRenderTargetAddressLow(low);
})
MAXWELL3D_CASE(depthTargetFormat, {
context.SetDepthRenderTargetFormat(depthTargetFormat);
})
MAXWELL3D_CASE(depthTargetTileMode, {
context.SetDepthRenderTargetTileMode(depthTargetTileMode);
})
MAXWELL3D_CASE(depthTargetLayerStride, {
context.SetDepthRenderTargetLayerStride(depthTargetLayerStride);
})
MAXWELL3D_CASE(depthTargetWidth, {
context.SetDepthRenderTargetWidth(depthTargetWidth);
})
MAXWELL3D_CASE(depthTargetHeight, {
context.SetDepthRenderTargetHeight(depthTargetHeight);
})
MAXWELL3D_CASE(depthTargetArrayMode, {
context.SetDepthRenderTargetArrayMode(depthTargetArrayMode);
})
#define VIEWPORT_TRANSFORM_CALLBACKS(z, index, data) \
MAXWELL3D_ARRAY_STRUCT_CASE(viewportTransforms, index, scaleX, { \
context.SetViewportX(index, scaleX, registers.viewportTransforms[index].translateX); \

View File

@ -109,8 +109,19 @@ namespace skyline::soc::gm20b::engine::maxwell3d {
Register<0x3E4, u32> commonColorWriteMask; //!< If enabled, the color write masks for all RTs must be set to that of the first RT
Register<0x3EB, u32> rtSeparateFragData;
Register<0x3F8, type::Address> depthTargetAddress;
Register<0x3FA, type::DepthRtFormat> depthTargetFormat;
Register<0x3FB, type::RenderTargetTileMode> depthTargetTileMode;
Register<0x3FC, u32> depthTargetLayerStride;
Register<0x458, std::array<type::VertexAttribute, type::VertexAttributeCount>> vertexAttributeState;
Register<0x487, type::RenderTargetControl> renderTargetControl;
Register<0x48A, u32> depthTargetWidth;
Register<0x48B, u32> depthTargetHeight;
Register<0x48C, type::RenderTargetArrayMode> depthTargetArrayMode;
Register<0x4B9, u32> independentBlendEnable;
Register<0x4BB, u32> alphaTestEnable;
Register<0x4C3, type::CompareOp> depthTestFunc;