[D3D12] 64bpp raw resolve and EDRAM refactoring

This commit is contained in:
Triang3l
2018-09-16 15:11:11 +03:00
parent 5be78ab369
commit c9ffe98d21
17 changed files with 188 additions and 106 deletions

View File

@@ -15,9 +15,9 @@ void main(uint3 xe_group_id : SV_GroupID,
any(sample_index >= clear_rect.zw)) {
return;
}
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 2u;
uint edram_offset = XeEDRAMOffset(xe_group_id.xy, tile_dword_index);
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 2u;
uint edram_offset = XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index);
xe_edram_load_store_dest.Store(edram_offset, xe_edram_clear_color32);
if (sample_index.x + 1u < clear_rect.z) {
xe_edram_load_store_dest.Store(edram_offset + 4u, xe_edram_clear_color32);

View File

@@ -15,11 +15,11 @@ void main(uint3 xe_group_id : SV_GroupID,
any(sample_index >= clear_rect.zw)) {
return;
}
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 2u;
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 2u;
bool second_sample_inside = sample_index.x + 1u < clear_rect.z;
// 24-bit depth.
uint edram_offset = XeEDRAMOffset(xe_group_id.xy, tile_dword_index);
uint edram_offset = XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index);
xe_edram_load_store_dest.Store(edram_offset, xe_edram_clear_depth24);
[branch] if (second_sample_inside) {
xe_edram_load_store_dest.Store(edram_offset + 4u, xe_edram_clear_depth24);

View File

@@ -4,11 +4,11 @@
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 4u;
uint4 pixels = xe_edram_load_store_source.Load4(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index));
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
uint4 samples = xe_edram_load_store_source.Load4(
XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index));
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
xe_edram_load_store_dest.Store4(rt_offset, pixels);
xe_edram_load_store_dest.Store4(rt_offset, samples);
}

View File

@@ -1,19 +1,14 @@
#include "edram_load_store.hlsli"
[numthreads(40, 8, 1)]
[numthreads(40, 16, 1)]
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
// One tile contains 80x8 texels, and 2 rows within a 80x16 tile contain data
// from 1 render target row rather than 1. Threads with X 0-19 are for the
// first row, with 20-39 are for the second.
uint2 tile_dword_index = xe_group_thread_id.xy * uint2(4u, 2u);
[flatten] if (xe_group_thread_id.x >= 20u) {
tile_dword_index += uint2(uint(-80), 1u);
}
uint4 pixels = xe_edram_load_store_source.Load4(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index));
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 2u;
uint4 samples = xe_edram_load_store_source.Load4(
XeEDRAMOffset64bpp(xe_group_id.xy, tile_sample_index));
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
xe_edram_load_store_dest.Store4(rt_offset, pixels);
xe_edram_load_store_dest.Store4(rt_offset, samples);
}

View File

@@ -5,16 +5,16 @@
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 2u;
uint2 pixels_7e3_packed = xe_edram_load_store_source.Load2(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index));
uint4 pixel_0_f16u32 = XeFloat7e3To16(pixels_7e3_packed.x);
uint4 pixel_1_f16u32 = XeFloat7e3To16(pixels_7e3_packed.y);
uint4 pixels_f16u32_packed =
uint4(pixel_0_f16u32.xz, pixel_1_f16u32.xz) |
(uint4(pixel_0_f16u32.yw, pixel_1_f16u32.yw) << 16u);
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 2u;
uint2 samples_7e3_packed = xe_edram_load_store_source.Load2(
XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index));
uint4 sample_0_f16u32 = XeFloat7e3To16(samples_7e3_packed.x);
uint4 sample_1_f16u32 = XeFloat7e3To16(samples_7e3_packed.y);
uint4 samples_f16u32_packed =
uint4(sample_0_f16u32.xz, sample_1_f16u32.xz) |
(uint4(sample_0_f16u32.yw, sample_1_f16u32.yw) << 16u);
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
xe_edram_load_store_dest.Store4(rt_offset, pixels_f16u32_packed);
xe_edram_load_store_dest.Store4(rt_offset, samples_f16u32_packed);
}

View File

@@ -5,9 +5,9 @@
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 4u;
uint edram_offset = XeEDRAMOffset(xe_group_id.xy, tile_dword_index);
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
uint edram_offset = XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index);
uint4 depth24_stencil = xe_edram_load_store_source.Load4(edram_offset);
uint4 depth24 = depth24_stencil >> 8u;
uint4 depth32 = xe_edram_load_store_source.Load4(10485760u + edram_offset);

View File

@@ -4,16 +4,16 @@
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 4u;
uint4 pixels = xe_edram_load_store_source.Load4(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index));
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
uint4 samples = xe_edram_load_store_source.Load4(
XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index));
// Depth.
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
xe_edram_load_store_dest.Store4(rt_offset, pixels >> 8u);
xe_edram_load_store_dest.Store4(rt_offset, samples >> 8u);
// Stencil.
uint4 stencil = (pixels & 0xFFu) << uint4(0u, 8u, 16u, 24u);
uint4 stencil = (samples & 0xFFu) << uint4(0u, 8u, 16u, 24u);
stencil.xy |= stencil.zw;
stencil.x |= stencil.y;
rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u +

View File

@@ -25,10 +25,10 @@ cbuffer XeEDRAMLoadStoreConstants : register(b0) {
// 16:17 - sample to load (16 - vertical index, 17 - horizontal index).
// 18:20 - destination endianness.
// 21:31 - BPP-specific info for swapping red/blue, 0 if not swapping.
// For 32 bits per pixel:
// For 32 bits per sample:
// 21:25 - red/blue bit depth.
// 26:30 - blue offset.
// For 64 bits per pixel, it's 1 if need to swap 0:15 and 32:47.
// For 64 bits per sample, it's 1 if need to swap 0:15 and 32:47.
#define xe_edram_tile_sample_dest_info (xe_edram_load_store_constants.w)
// For clearing.
@@ -45,10 +45,20 @@ ByteAddressBuffer xe_edram_load_store_source : register(t0);
#endif
RWByteAddressBuffer xe_edram_load_store_dest : register(u0);
uint XeEDRAMOffset(uint2 tile_index, uint2 tile_dword_index) {
uint XeEDRAMOffset32bpp(uint2 tile_index, uint2 tile_sample_index) {
return ((xe_edram_base_pitch_tiles & 2047u) +
tile_index.y * (xe_edram_base_pitch_tiles >> 11u) + tile_index.x) *
5120u + tile_dword_index.y * 320u + tile_dword_index.x * 4u;
5120u + tile_sample_index.y * 320u + tile_sample_index.x * 4u;
}
// Instead of individual tiles, this works on two consecutive tiles, the first
// one containing the top 80x8 samples, and the second one containing the bottom
// 80x8 samples.
uint XeEDRAMOffset64bpp(uint2 tile_pair_index, uint2 tile_pair_sample_index) {
return ((xe_edram_base_pitch_tiles & 2047u) +
tile_pair_index.y * (xe_edram_base_pitch_tiles >> 11u) +
(tile_pair_index.x << 1u)) * 5120u +
tile_pair_sample_index.y * 640u + tile_pair_sample_index.x * 8u;
}
#endif // XENIA_GPU_D3D12_SHADERS_EDRAM_LOAD_STORE_HLSLI_

View File

@@ -6,9 +6,9 @@ void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
uint4 pixels = xe_edram_load_store_source.Load4(rt_offset);
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 4u;
uint4 samples = xe_edram_load_store_source.Load4(rt_offset);
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
xe_edram_load_store_dest.Store4(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index), pixels);
XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index), samples);
}

View File

@@ -1,19 +1,14 @@
#include "edram_load_store.hlsli"
[numthreads(40, 8, 1)]
[numthreads(40, 16, 1)]
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
uint4 pixels = xe_edram_load_store_source.Load4(rt_offset);
// One tile contains 80x8 texels, and 2 rows within a 80x16 tile contain data
// from 1 render target row rather than 1. Threads with X 0-19 are for the
// first row, with 20-39 are for the second.
uint2 tile_dword_index = xe_group_thread_id.xy * uint2(4u, 2u);
[flatten] if (xe_group_thread_id.x >= 20u) {
tile_dword_index += uint2(uint(-80), 1u);
}
uint4 samples = xe_edram_load_store_source.Load4(rt_offset);
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 2u;
xe_edram_load_store_dest.Store4(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index), pixels);
XeEDRAMOffset64bpp(xe_group_id.xy, tile_sample_index), samples);
}

View File

@@ -7,13 +7,14 @@ void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_thread_id : SV_DispatchThreadID) {
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
uint4 pixels_f16u32_packed = xe_edram_load_store_source.Load4(rt_offset);
uint4 pixel_0_f16u32 = pixels_f16u32_packed.xxyy >> uint4(0u, 16u, 0u, 16u);
uint4 pixel_1_f16u32 = pixels_f16u32_packed.zzww >> uint4(0u, 16u, 0u, 16u);
uint2 pixels_7e3_packed =
uint2(XeFloat16To7e3(pixel_0_f16u32), XeFloat16To7e3(pixel_1_f16u32));
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 2u;
uint4 samples_f16u32_packed = xe_edram_load_store_source.Load4(rt_offset);
uint4 sample_0_f16u32 = samples_f16u32_packed.xxyy >> uint4(0u, 16u, 0u, 16u);
uint4 sample_1_f16u32 = samples_f16u32_packed.zzww >> uint4(0u, 16u, 0u, 16u);
uint2 samples_7e3_packed =
uint2(XeFloat16To7e3(sample_0_f16u32), XeFloat16To7e3(sample_1_f16u32));
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 2u;
xe_edram_load_store_dest.Store2(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index), pixels_7e3_packed);
XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index),
samples_7e3_packed);
}

View File

@@ -15,9 +15,9 @@ void main(uint3 xe_group_id : SV_GroupID,
xe_edram_rt_stencil_offset;
depth24_stencil |= (xe_edram_load_store_source.Load(rt_offset).xxxx >>
uint4(0u, 8u, 16u, 24u)) & 0xFFu;
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 4u;
uint edram_offset = XeEDRAMOffset(xe_group_id.xy, tile_dword_index);
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
uint edram_offset = XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index);
// Store 24-bit depth for aliasing and checking if 32-bit depth is up to date.
xe_edram_load_store_dest.Store4(edram_offset, depth24_stencil);
// Store 32-bit depth so precision isn't lost when doing multipass rendering.

View File

@@ -7,15 +7,15 @@ void main(uint3 xe_group_id : SV_GroupID,
// Depth.
uint rt_offset = xe_thread_id.y * xe_edram_rt_color_depth_pitch +
xe_thread_id.x * 16u + xe_edram_rt_color_depth_offset;
uint4 pixels =
uint4 samples =
(xe_edram_load_store_source.Load4(rt_offset) & 0xFFFFFFu) << 8u;
// Stencil.
rt_offset = xe_thread_id.y * xe_edram_rt_stencil_pitch + xe_thread_id.x * 4u +
xe_edram_rt_stencil_offset;
pixels |= (xe_edram_load_store_source.Load(rt_offset).xxxx >>
samples |= (xe_edram_load_store_source.Load(rt_offset).xxxx >>
uint4(0u, 8u, 16u, 24u)) & 0xFFu;
uint2 tile_dword_index = xe_group_thread_id.xy;
tile_dword_index.x *= 4u;
uint2 tile_sample_index = xe_group_thread_id.xy;
tile_sample_index.x *= 4u;
xe_edram_load_store_dest.Store4(
XeEDRAMOffset(xe_group_id.xy, tile_dword_index), pixels);
XeEDRAMOffset32bpp(xe_group_id.xy, tile_sample_index), samples);
}

View File

@@ -23,7 +23,7 @@ void main(uint3 xe_group_id : SV_GroupID,
(xe_edram_tile_sample_dest_info.xxxx >> uint4(15u, 14u, 17u, 16u)) & 1u;
uint2 edram_tile_quarter =
uint2(uint2(10u, 8u) <= xe_group_thread_id.xy) * sample_info.xy;
uint edram_offset = XeEDRAMOffset(
uint edram_offset = XeEDRAMOffset32bpp(
(xe_group_id.xy << sample_info.xy) + edram_tile_quarter,
(xe_group_thread_id.xy - edram_tile_quarter * uint2(10u, 8u)) <<
(sample_info.xy + uint2(2u, 0u)) + sample_info.zw);

View File

@@ -0,0 +1,67 @@
#include "byte_swap.hlsli"
#include "edram_load_store.hlsli"
#include "texture_address.hlsli"
[numthreads(20, 16, 1)]
void main(uint3 xe_group_id : SV_GroupID,
uint3 xe_group_thread_id : SV_GroupThreadID,
uint3 xe_thread_id : SV_DispatchThreadID) {
// Check if not outside of the destination texture completely.
uint4 copy_rect;
copy_rect.xz = xe_edram_tile_sample_rect & 0xFFFFu;
copy_rect.yw = xe_edram_tile_sample_rect >> 16u;
uint2 texel_index = xe_thread_id.xy;
texel_index.x *= 4u;
[branch] if (any(texel_index < copy_rect.xy) ||
any(texel_index >= copy_rect.zw)) {
return;
}
// Get the samples from the EDRAM buffer.
// XY - log2(pixel size), ZW - selected sample offset.
uint4 sample_info =
(xe_edram_tile_sample_dest_info.xxxx >> uint4(15u, 14u, 17u, 16u)) & 1u;
uint2 edram_tile_quarter =
uint2(uint2(10u, 8u) <= xe_group_thread_id.xy) * sample_info.xy;
uint edram_offset = XeEDRAMOffset64bpp(
(xe_group_id.xy << sample_info.xy) + edram_tile_quarter,
(xe_group_thread_id.xy - edram_tile_quarter * uint2(10u, 8u)) <<
(sample_info.xy + uint2(2u, 0u)) + sample_info.zw);
// Loaded with the first 2 pixels at 1x and 2x, or the first 1 pixel at 4x.
uint4 pixels_01 = xe_edram_load_store_source.Load4(edram_offset);
// Loaded with the second 2 pixels at 1x and 2x, or the second 1 pixel at 4x.
uint4 pixels_23 = xe_edram_load_store_source.Load4(edram_offset + 16u);
[branch] if (sample_info.x != 0u) {
// Rather than 4 pixels, at 4x, we only have 2 - in xy of each variable
// rather than in xyzw of pixels_01. Combine and load 2 more.
pixels_01.zw = pixels_23.xy;
pixels_23.xy = xe_edram_load_store_source.Load2(edram_offset + 32u);
pixels_23.zw = xe_edram_load_store_source.Load2(edram_offset + 48u);
}
if ((xe_edram_tile_sample_dest_info >> 21u) != 0u) {
// Swap red and blue - all 64bpp formats where this is possible are
// 16:16:16:16.
pixels_01 = (pixels_01 & 0xFFFF0000u) | (pixels_01.yxwz & 0xFFFFu);
pixels_23 = (pixels_23 & 0xFFFF0000u) | (pixels_23.yxwz & 0xFFFFu);
}
// Tile the pixels to the shared memory.
pixels_01 = XeByteSwap(pixels_01, xe_edram_tile_sample_dest_info >> 18u);
pixels_23 = XeByteSwap(pixels_23, xe_edram_tile_sample_dest_info >> 18u);
uint4 texel_addresses =
xe_edram_tile_sample_dest_base +
XeTextureTiledOffset2D(texel_index - copy_rect.xy,
xe_edram_tile_sample_dest_info & 16383u, 3u);
xe_edram_load_store_dest.Store2(texel_addresses.x, pixels_01.xy);
bool3 texels_in_rect = uint3(1u, 2u, 3u) + texel_index.x < copy_rect.z;
[branch] if (texels_in_rect.x) {
xe_edram_load_store_dest.Store2(texel_addresses.y, pixels_01.zw);
[branch] if (texels_in_rect.y) {
xe_edram_load_store_dest.Store2(texel_addresses.z, pixels_23.xy);
[branch] if (texels_in_rect.z) {
xe_edram_load_store_dest.Store2(texel_addresses.w, pixels_23.zw);
}
}
}
}