[D3D12] Take 0 being bottom-right sample with 2x MSAA in D3D12 into account

This commit is contained in:
Triang3l
2021-06-06 20:58:50 +03:00
parent c4a5048e62
commit 3f156f26c4
3 changed files with 130 additions and 82 deletions

View File

@@ -3081,10 +3081,11 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
uint32_t source_tile_pixel_x_reg = 0;
uint32_t source_tile_pixel_y_reg = 0;
// First sample bit at 4x - horizontal sample.
// Second sample bit at 4x - vertical sample.
// At 2x, the vertical sample is either the first or the second bit
// depending on whether 2x is emulated as 4x.
// First sample bit at 4x in Direct3D 10.1+ - horizontal sample.
// Second sample bit at 4x in Direct3D 10.1+ - vertical sample.
// At 2x:
// - Native 2x: top is 1 in Direct3D 10.1+, bottom is 0.
// - 2x as 4x: top is 0, bottom is 3.
if (!source_is_64bpp && dest_is_64bpp) {
// 32bpp -> 64bpp, need two samples of the source.
@@ -3113,14 +3114,15 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
// D p0,0 s1 = S p0,0 s0,1 | S p0,0 s1,1
// D p1,0 s0 = S p1,0 s0,0 | S p1,0 s1,0
// D p1,0 s1 = S p1,0 s0,1 | S p1,0 s1,1
// Pixel index can be reused. Sample 0 should become samples 01,
// sample 1 or 3 should become samples 23.
// Pixel index can be reused. Sample 1 (for native 2x) or 0 (for 2x as
// 4x) should become samples 01, sample 0 or 3 should become samples 23.
source_sample = dxbc::Src::R(1, dxbc::Src::kZZZZ);
if (msaa_2x_supported_) {
a.OpIShL(dxbc::Dest::R(1, 0b0100), dest_sample, dxbc::Src::LU(1));
a.OpXOr(dxbc::Dest::R(1, 0b0100), dest_sample, dxbc::Src::LU(1));
a.OpIShL(dxbc::Dest::R(1, 0b0100), source_sample, dxbc::Src::LU(1));
} else {
a.OpAnd(dxbc::Dest::R(1, 0b0100), dest_sample, dxbc::Src::LU(0b10));
}
source_sample = dxbc::Src::R(1, dxbc::Src::kZZZZ);
} else {
// 32bpp -> 64bpp, 4x -> 1x.
// 1 destination horizontal pixel = 2 source horizontal samples.
@@ -3201,11 +3203,14 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
source_sample = dxbc::Src::R(1, dxbc::Src::kZZZZ);
if (key.dest_msaa_samples == xenos::MsaaSamples::k2X) {
// 64bpp -> 32bpp, 4x -> 2x.
// Destination vertical samples (first or second bit, depending on
// support) = source vertical samples (second bit).
// Destination vertical samples (1/0 in the first bit for native 2x or
// 0/1 in the second bit for 2x as 4x) = source vertical samples
// (second bit).
if (msaa_2x_supported_) {
a.OpBFI(dxbc::Dest::R(1, 0b0100), dxbc::Src::LU(1),
dxbc::Src::LU(1), dest_sample, source_sample);
a.OpXOr(dxbc::Dest::R(1, 0b0100), source_sample,
dxbc::Src::LU(1 << 1));
} else {
a.OpBFI(dxbc::Dest::R(1, 0b0100), dxbc::Src::LU(1),
dxbc::Src::LU(0), source_sample, dest_sample);
@@ -3244,18 +3249,21 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
// Same BPP, 4x -> 1x/2x.
if (key.dest_msaa_samples == xenos::MsaaSamples::k2X) {
// Same BPP, 4x -> 2x.
// Horizontal pixels to samples. Vertical sample (first or second bit,
// depending on support) to second sample bit.
// Horizontal pixels to samples. Vertical sample (1/0 in the first bit
// for native 2x or 0/1 in the second bit for 2x as 4x) to second
// sample bit.
source_sample = dxbc::Src::R(1, dxbc::Src::kZZZZ);
if (msaa_2x_supported_) {
a.OpBFI(dxbc::Dest::R(1, 0b0100), dxbc::Src::LU(31),
dxbc::Src::LU(1), dest_sample,
dxbc::Src::R(0, dxbc::Src::kXXXX));
a.OpXOr(dxbc::Dest::R(1, 0b0100), source_sample,
dxbc::Src::LU(1 << 1));
} else {
a.OpBFI(dxbc::Dest::R(1, 0b0100), dxbc::Src::LU(1),
dxbc::Src::LU(0), dxbc::Src::R(0, dxbc::Src::kXXXX),
dest_sample);
}
source_sample = dxbc::Src::R(1, dxbc::Src::kZZZZ);
a.OpUShR(dxbc::Dest::R(1, 0b0001), dxbc::Src::R(0, dxbc::Src::kXXXX),
dxbc::Src::LU(1));
source_tile_pixel_x_reg = 1;
@@ -3292,10 +3300,12 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
if (key.source_msaa_samples == xenos::MsaaSamples::k2X) {
// 2x -> 4x.
// Vertical samples (second bit) of 4x destination to vertical sample
// (01 or 03, depending on support) of 2x source.
// (1, 0 for native 2x, or 0, 3 for 2x as 4x) of 2x source.
a.OpUShR(dxbc::Dest::R(1, 0b0100), dest_sample, dxbc::Src::LU(1));
source_sample = dxbc::Src::R(1, dxbc::Src::kZZZZ);
if (!msaa_2x_supported_) {
if (msaa_2x_supported_) {
a.OpXOr(dxbc::Dest::R(1, 0b0100), source_sample, dxbc::Src::LU(1));
} else {
a.OpBFI(dxbc::Dest::R(1, 0b0100), dxbc::Src::LU(1), dxbc::Src::LU(1),
source_sample, source_sample);
}
@@ -3312,12 +3322,14 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
// 1x/2x -> different 1x/2x.
if (key.source_msaa_samples == xenos::MsaaSamples::k2X) {
// 2x -> 1x.
// Vertical pixels of 2x destination to vertical samples (01 or 03,
// depending on support) of 1x source.
// Vertical pixels of 2x destination to vertical samples (1, 0 for
// native 2x, or 0, 3 for 2x as 4x) of 1x source.
a.OpAnd(dxbc::Dest::R(1, 0b0100), dxbc::Src::R(0, dxbc::Src::kYYYY),
dxbc::Src::LU(1));
source_sample = dxbc::Src::R(1, dxbc::Src::kZZZZ);
if (!msaa_2x_supported_) {
if (msaa_2x_supported_) {
a.OpXOr(dxbc::Dest::R(1, 0b0100), source_sample, dxbc::Src::LU(1));
} else {
a.OpBFI(dxbc::Dest::R(1, 0b0100), dxbc::Src::LU(1), dxbc::Src::LU(1),
source_sample, source_sample);
}
@@ -3326,15 +3338,20 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
source_tile_pixel_y_reg = 1;
} else {
// 1x -> 2x.
// Vertical samples (first or second bit, depending on support) of 2x
// destination to vertical pixels of 1x source.
if (!msaa_2x_supported_) {
// Vertical samples (1/0 in the first bit for native 2x or 0/1 in the
// second bit for 2x as 4x) of 2x destination to vertical pixels of 1x
// source.
if (msaa_2x_supported_) {
a.OpBFI(dxbc::Dest::R(1, 0b0010), dxbc::Src::LU(31), dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kYYYY), dest_sample);
a.OpXOr(dxbc::Dest::R(1, 0b0010), dxbc::Src::R(1, dxbc::Src::kYYYY),
dxbc::Src::LU(1));
} else {
a.OpUShR(dxbc::Dest::R(1, 0b0010), dest_sample, dxbc::Src::LU(1));
a.OpBFI(dxbc::Dest::R(1, 0b0010), dxbc::Src::LU(31), dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kYYYY),
dxbc::Src::R(1, dxbc::Src::kYYYY));
}
a.OpBFI(dxbc::Dest::R(1, 0b0010), dxbc::Src::LU(31), dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kYYYY),
msaa_2x_supported_ ? dest_sample
: dxbc::Src::R(1, dxbc::Src::kYYYY));
source_tile_pixel_y_reg = 1;
}
}
@@ -3935,13 +3952,15 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
dxbc::Src::LU(1), dxbc::Src::R(0, dxbc::Src::kXXXX),
dest_sample);
}
// Vertical sample index in bit 0 for true 2x or in bit 1 for
// 4x or for 2x emulated as 4x.
// Vertical sample index as 1 or 0 in bit 0 for true 2x or as 0
// or 1 in bit 1 for 4x or for 2x emulated as 4x.
if (key.dest_msaa_samples == xenos::MsaaSamples::k2X &&
msaa_2x_supported_) {
a.OpBFI(dxbc::Dest::R(0, 0b0010), dxbc::Src::LU(31),
dxbc::Src::LU(1), dxbc::Src::R(0, dxbc::Src::kYYYY),
dest_sample);
a.OpXOr(dxbc::Dest::R(0, 0b0010),
dxbc::Src::R(0, dxbc::Src::kYYYY), dxbc::Src::LU(1));
} else {
// Using r0.w as a temporary.
a.OpUShR(dxbc::Dest::R(0, 0b1000), dest_sample,
@@ -3993,19 +4012,22 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
// 4x -> 1x/2x.
if (key.dest_msaa_samples == xenos::MsaaSamples::k2X) {
// 4x -> 2x.
// Horizontal pixels to samples. Vertical sample (first or
// second bit, depending on support) to second sample bit.
// Horizontal pixels to samples. Vertical sample (1, 0 in
// the first bit for native 2x or 0, 1 in the second bit for
// 2x as 4x) to second sample bit.
host_depth_source_sample =
dxbc::Src::R(0, dxbc::Src::kWWWW);
if (msaa_2x_supported_) {
a.OpBFI(dxbc::Dest::R(0, 0b1000), dxbc::Src::LU(31),
dxbc::Src::LU(1), dest_sample,
dxbc::Src::R(0, dxbc::Src::kXXXX));
a.OpXOr(dxbc::Dest::R(0, 0b1000),
host_depth_source_sample, dxbc::Src::LU(1 << 1));
} else {
a.OpBFI(dxbc::Dest::R(0, 0b1000), dxbc::Src::LU(1),
dxbc::Src::LU(0),
dxbc::Src::R(0, dxbc::Src::kXXXX), dest_sample);
}
host_depth_source_sample =
dxbc::Src::R(0, dxbc::Src::kWWWW);
a.OpUShR(dxbc::Dest::R(0, 0b0001),
dxbc::Src::R(0, dxbc::Src::kXXXX),
dxbc::Src::LU(1));
@@ -4042,13 +4064,16 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
xenos::MsaaSamples::k2X) {
// 2x -> 4x.
// Vertical samples (second bit) of 4x destination to
// vertical sample (01 or 03, depending on support) of 2x
// source.
// vertical sample (1, 0 for native 2x, or 0, 3 for 2x as
// 4x) of 2x source.
a.OpUShR(dxbc::Dest::R(0, 0b1000), dest_sample,
dxbc::Src::LU(1));
host_depth_source_sample =
dxbc::Src::R(0, dxbc::Src::kWWWW);
if (!msaa_2x_supported_) {
if (msaa_2x_supported_) {
a.OpXOr(dxbc::Dest::R(0, 0b1000),
host_depth_source_sample, dxbc::Src::LU(1));
} else {
a.OpBFI(dxbc::Dest::R(0, 0b1000), dxbc::Src::LU(1),
dxbc::Src::LU(1), host_depth_source_sample,
host_depth_source_sample);
@@ -4070,13 +4095,17 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
xenos::MsaaSamples::k2X) {
// 2x -> 1x.
// Vertical pixels of 2x destination to vertical samples
// (01 or 03, depending on support) of 1x source.
// (1, 0 for native 2x, or 0, 3 for 2x as 4x) of 1x
// source.
a.OpAnd(dxbc::Dest::R(0, 0b1000),
dxbc::Src::R(0, dxbc::Src::kYYYY),
dxbc::Src::LU(1));
host_depth_source_sample =
dxbc::Src::R(0, dxbc::Src::kWWWW);
if (!msaa_2x_supported_) {
if (msaa_2x_supported_) {
a.OpXOr(dxbc::Dest::R(0, 0b1000),
host_depth_source_sample, dxbc::Src::LU(1));
} else {
a.OpBFI(dxbc::Dest::R(0, 0b1000), dxbc::Src::LU(1),
dxbc::Src::LU(1), host_depth_source_sample,
host_depth_source_sample);
@@ -4086,21 +4115,26 @@ D3D12RenderTargetCache::GetOrCreateTransferPipelines(TransferShaderKey key) {
dxbc::Src::LU(1));
} else {
// 1x -> 2x.
// Vertical samples (first or second bit, depending on
// support) of 2x destination to vertical pixels of 1x
// source.
// Vertical samples (1, 0 in the first bit for native 2x
// or 0, 1 in the second bit for 2x as 4x) of 2x
// destination to vertical pixels of 1x source.
// Using r0.w (not needed without source MSAA) as a
// temporary.
if (!msaa_2x_supported_) {
if (msaa_2x_supported_) {
a.OpBFI(dxbc::Dest::R(0, 0b0010), dxbc::Src::LU(31),
dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kYYYY), dest_sample);
a.OpXOr(dxbc::Dest::R(0, 0b0010),
dxbc::Src::R(0, dxbc::Src::kYYYY),
dxbc::Src::LU(1));
} else {
a.OpUShR(dxbc::Dest::R(0, 0b1000), dest_sample,
dxbc::Src::LU(1));
a.OpBFI(dxbc::Dest::R(0, 0b0010), dxbc::Src::LU(31),
dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kYYYY),
dxbc::Src::R(0, dxbc::Src::kWWWW));
}
a.OpBFI(dxbc::Dest::R(0, 0b0010), dxbc::Src::LU(31),
dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kYYYY),
msaa_2x_supported_
? dest_sample
: dxbc::Src::R(0, dxbc::Src::kWWWW));
}
}
}
@@ -6038,7 +6072,7 @@ ID3D12PipelineState* D3D12RenderTargetCache::GetOrCreateDumpPipeline(
dxbc::Src::LU(xenos::kEdramTileWidthSamples >>
uint32_t(format_is_64bpp)),
dxbc::Src::VThreadIDInGroup(dxbc::Src::kXXXX));
// r0.w for 4x MSAA = pixel Y in the group
// r0.w for 2x MSAA = pixel Y in the group
a.OpUShR(dxbc::Dest::R(0, 0b1000),
dxbc::Src::VThreadIDInGroup(dxbc::Src::kYYYY), dxbc::Src::LU(1));
// r0.w = free
@@ -6067,7 +6101,7 @@ ID3D12PipelineState* D3D12RenderTargetCache::GetOrCreateDumpPipeline(
if (key.msaa_samples != xenos::MsaaSamples::k1X) {
// Sample index.
// For 4x, bit 0 for horizontal, bit 1 for vertical.
// For 2x, only vertical - but 0 or 1 for true 2x MSAA or 0 or 3 for 2x MSAA
// For 2x, only vertical - but 1 or 0 for true 2x MSAA or 0 or 3 for 2x MSAA
// via two samples of 4x.
// r0.w = vertical sample index
a.OpAnd(dxbc::Dest::R(0, 0b1000),
@@ -6077,11 +6111,17 @@ ID3D12PipelineState* D3D12RenderTargetCache::GetOrCreateDumpPipeline(
a.OpBFI(dxbc::Dest::R(0, 0b1000), dxbc::Src::LU(31), dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kWWWW),
dxbc::Src::VThreadIDInGroup(dxbc::Src::kXXXX));
} else if (!msaa_2x_supported_) {
// r0.w = source sample 0 or 3 for 2x MSAA emulated via 4x
a.OpBFI(dxbc::Dest::R(0, 0b1000), dxbc::Src::LU(1), dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kWWWW),
dxbc::Src::R(0, dxbc::Src::kWWWW));
} else {
if (msaa_2x_supported_) {
// r0.w = source sample 1 or 0 for native 2x MSAA
a.OpXOr(dxbc::Dest::R(0, 0b1000), dxbc::Src::R(0, dxbc::Src::kWWWW),
dxbc::Src::LU(1));
} else {
// r0.w = source sample 0 or 3 for 2x MSAA emulated via 4x
a.OpBFI(dxbc::Dest::R(0, 0b1000), dxbc::Src::LU(1), dxbc::Src::LU(1),
dxbc::Src::R(0, dxbc::Src::kWWWW),
dxbc::Src::R(0, dxbc::Src::kWWWW));
}
}
}