Files
Xenia-Canary/src/xenia/gpu/shaders/resolve.xesli
Triang3l b61953374e [GPU] Make resolve EDRAM binding DS 0 and rename it
Ordering the descriptor sets by the change frequency on Vulkan, in increasing order (the opposite of D3D12 root signatures). The EDRAM binding never changes there (always one storage buffer), while the destination buffer binding may become changeable in the future (to split dispatches if exceeding `maxStorageBufferRange`, for example).
2022-06-20 12:15:52 +03:00

819 lines
36 KiB
Plaintext

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2022 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_GPU_SHADERS_RESOLVE_XESLI_
#define XENIA_GPU_SHADERS_RESOLVE_XESLI_
#include "edram.xesli"
#include "pixel_formats.xesli"
#include "texture_address.xesli"
#define kXenosCopySampleSelect_0 0u
#define kXenosCopySampleSelect_1 1u
#define kXenosCopySampleSelect_2 2u
#define kXenosCopySampleSelect_3 3u
#define kXenosCopySampleSelect_01 4u
#define kXenosCopySampleSelect_23 5u
#define kXenosCopySampleSelect_0123 6u
xesl_pushConstants_begin(b0, space0)
#ifdef XE_RESOLVE_CLEAR
xesl_uint2 xe_resolve_clear_value;
#endif
// xe::gpu::draw_util::ResolveEdramInfo.
uint xe_resolve_edram_info;
// xe::gpu::draw_util::ResolveCoordinateInfo.
uint xe_resolve_coordinate_info;
#ifndef XE_RESOLVE_CLEAR
// Sanitized RB_COPY_DEST_INFO.
uint xe_resolve_dest_info;
// xe::gpu::draw_util::ResolveCopyDestCoordinateInfo.
uint xe_resolve_dest_coordinate_info;
#ifndef XE_RESOLVE_RESOLUTION_SCALED
uint xe_resolve_dest_base;
#endif
#endif
xesl_pushConstants_end
#define XE_RESOLVE_PUSH_CONSTANTS_BINDING xesl_pushConstants_binding(buffer(0))
#ifndef XE_RESOLVE_CLEAR
#ifdef XE_RESOLVE_COPY_EDRAM_IS_UINT_VECTOR_BUFFER
xesl_uintVectorBuffer_declare(xe_resolve_edram, set=0, binding=0, t0,
space0)
#define XE_RESOLVE_COPY_EDRAM_BINDING \
xesl_uintVectorBuffer_binding(xe_resolve_edram, buffer(2))
#else
xesl_typedStorageBuffer_declare(XE_RESOLVE_SOURCE_TYPE, xe_resolve_edram,
set=0, binding=0, t0, space0)
#define XE_RESOLVE_COPY_EDRAM_BINDING \
xesl_typedStorageBuffer_binding(XE_RESOLVE_SOURCE_TYPE, \
xe_resolve_edram, buffer(2))
#endif
#endif
struct XeResolveInfo {
uint edram_pitch_tiles;
uint edram_msaa_samples;
// Always false for non-one-to-one resolve.
bool edram_is_depth;
uint edram_base_tiles;
uint edram_format;
uint edram_format_ints_log2;
xesl_uint2 resolution_scale;
xesl_bool2 duplicate_second_host_pixel;
xesl_uint2 edram_offset_scaled;
uint width_div_8_scaled;
#ifdef XE_RESOLVE_CLEAR
xesl_uint2 clear_value;
#else
uint dest_endian_128;
bool dest_is_array;
uint dest_slice;
uint dest_format;
float dest_exp_bias_factor;
bool dest_swap;
uint dest_row_pitch_aligned;
uint dest_slice_pitch_aligned;
xesl_uint2 dest_xy_offset_scaled;
uint sample_select;
uint dest_base;
#endif // XE_RESOLVE_CLEAR
};
XeResolveInfo XeResolveGetInfo(xesl_function_param_pushConstants) {
XeResolveInfo resolve_info;
uint edram_info = xesl_pushConstant(xe_resolve_edram_info);
uint coordinate_info = xesl_pushConstant(xe_resolve_coordinate_info);
resolve_info.edram_pitch_tiles = edram_info & ((1u << 10u) - 1u);
resolve_info.edram_msaa_samples = (edram_info >> 10u) & ((1u << 2u) - 1u);
resolve_info.edram_is_depth = (edram_info & (1u << 12u)) != 0u;
resolve_info.edram_base_tiles = (edram_info >> 13u) & ((1u << 12u) - 1u);
resolve_info.edram_format = (edram_info >> 25u) & ((1u << 4u) - 1u);
resolve_info.edram_format_ints_log2 = (edram_info >> 29u) & 1u;
#ifdef XE_RESOLVE_RESOLUTION_SCALED
resolve_info.resolution_scale =
(xesl_uint_x2(coordinate_info) >> xesl_uint2(27u, 29u)) & 3u;
if ((edram_info & (1u << 30u)) != 0u) {
resolve_info.duplicate_second_host_pixel =
xesl_greaterThan(resolve_info.resolution_scale, xesl_uint_x2(1u));
} else {
resolve_info.duplicate_second_host_pixel = xesl_bool_x2(false);
}
#else
resolve_info.resolution_scale = xesl_uint_x2(1u);
resolve_info.duplicate_second_host_pixel = xesl_bool_x2(false);
#endif
resolve_info.edram_offset_scaled =
(((xesl_uint_x2(coordinate_info) >> xesl_uint2(0u, 4u)) &
((xesl_uint_x2(1u) << xesl_uint2(4u, 1u)) - 1u)) <<
3u) *
resolve_info.resolution_scale;
resolve_info.width_div_8_scaled =
((coordinate_info >> 5u) & ((1u << 11u) - 1u)) *
resolve_info.resolution_scale.x;
#ifdef XE_RESOLVE_CLEAR
resolve_info.clear_value = xesl_pushConstant(xe_resolve_clear_value);
#else
uint dest_info = xesl_pushConstant(xe_resolve_dest_info);
uint dest_coordinate_info =
xesl_pushConstant(xe_resolve_dest_coordinate_info);
resolve_info.dest_endian_128 = dest_info & ((1u << 3u) - 1u);
resolve_info.dest_is_array = (dest_info & (1u << 3u)) != 0u;
resolve_info.dest_slice = (dest_info >> 4u) & ((1u << 3u) - 1u);
resolve_info.dest_format = (dest_info >> 7u) & ((1u << 6u) - 1u);
resolve_info.dest_exp_bias_factor = xesl_intBitsToFloat(
(int(dest_info) << (32 - (16 + 6)) >> (32 - 6) << 23) +
xesl_floatBitsToInt(1.0f));
resolve_info.dest_swap = (dest_info & (1u << 24u)) != 0u;
resolve_info.dest_row_pitch_aligned =
(dest_coordinate_info & ((1u << 10u) - 1u)) << 5u;
resolve_info.dest_slice_pitch_aligned =
((dest_coordinate_info >> 10u) & ((1u << 10u) - 1u)) << 5u;
resolve_info.dest_xy_offset_scaled =
(((xesl_uint_x2(dest_coordinate_info) >> xesl_uint2(20u, 24u)) &
((1u << 4u) - 1u)) <<
3u) *
resolve_info.resolution_scale;
resolve_info.sample_select =
(dest_coordinate_info >> 28u) & ((1u << 3u) - 1u);
#ifndef XE_RESOLVE_RESOLUTION_SCALED
resolve_info.dest_base = xesl_pushConstant(xe_resolve_dest_base);
#else
resolve_info.dest_base = 0;
#endif
#endif // XE_RESOLVE_CLEAR
return resolve_info;
}
uint XeResolveEdramPixelStrideInts(XeResolveInfo resolve_info) {
return 1u << (resolve_info.edram_format_ints_log2 +
uint(resolve_info.edram_msaa_samples >= kXenosMsaaSamples_4X));
}
#ifndef XE_RESOLVE_CLEAR
uint XeResolveDestPixelAddress(XeResolveInfo resolve_info, xesl_uint2 p,
uint bpp_log2) {
p += resolve_info.dest_xy_offset_scaled;
uint address;
#ifdef XE_RESOLVE_RESOLUTION_SCALED
address = XeTextureScaledTiledOffset(
resolve_info.dest_is_array, xesl_uint3(p, resolve_info.dest_slice),
resolve_info.dest_row_pitch_aligned,
resolve_info.dest_slice_pitch_aligned, bpp_log2,
resolve_info.resolution_scale);
#else
xesl_dont_flatten if (resolve_info.dest_is_array) {
address = uint(XeTextureTiledOffset3D(
xesl_int3(xesl_uint3(p, resolve_info.dest_slice)),
resolve_info.dest_row_pitch_aligned,
resolve_info.dest_slice_pitch_aligned, bpp_log2));
} else {
address = uint(XeTextureTiledOffset2D(
xesl_int2(p), resolve_info.dest_row_pitch_aligned, bpp_log2));
}
address += resolve_info.dest_base;
#endif
return address;
}
// Offset of the beginning of the odd R32G32/R32G32B32A32 store address from
// the address of the even store.
uint XeResolveDestRightConsecutiveBlocksOffset(uint x, uint bpp_log2,
xesl_uint2 resolution_scale) {
#ifdef XE_RESOLVE_RESOLUTION_SCALED
return XeTextureScaledRightSubUnitOffsetInConsecutivePair(
x, bpp_log2, resolution_scale);
#else
return XeTextureTiledOddConsecutiveBlocksOffset(bpp_log2);
#endif
}
#define kXenosCopySampleSelect_0 0u
#define kXenosCopySampleSelect_1 1u
#define kXenosCopySampleSelect_2 2u
#define kXenosCopySampleSelect_3 3u
#define kXenosCopySampleSelect_01 4u
#define kXenosCopySampleSelect_23 5u
#define kXenosCopySampleSelect_0123 6u
uint XeResolveFirstSampleIndex(uint sample_select) {
uint sample_index;
if (sample_select <= kXenosCopySampleSelect_3) {
sample_index = sample_select;
} else if (sample_select == kXenosCopySampleSelect_23) {
sample_index = 2u;
} else {
sample_index = 0u;
}
return sample_index;
}
// Offset to the first sample to participate in averaging (or the sample to be
// copied if not averaging).
uint XeResolveColorCopySourcePixelAddressIntsYDuplicating(
XeResolveInfo resolve_info, xesl_uint2 pixel_index) {
return XeEdramOffsetInts(
xesl_uint2(pixel_index.x,
max(pixel_index.y,
uint(resolve_info.duplicate_second_host_pixel.y))) +
resolve_info.edram_offset_scaled,
resolve_info.edram_base_tiles, resolve_info.edram_pitch_tiles,
resolve_info.edram_msaa_samples, false,
resolve_info.edram_format_ints_log2,
XeResolveFirstSampleIndex(resolve_info.sample_select),
resolve_info.resolution_scale);
}
// Not using arrays for multi-pixel function arguments because they are
// compiled into indexable temps by FXC.
void XeResolveUnpack32bpp2Samples(
xesl_uint2 packed, uint format,
xesl_function_param_out(xesl_float4, sample_0),
xesl_function_param_out(xesl_float4, sample_1)) {
switch (format) {
case kXenosColorRenderTargetFormat_8_8_8_8:
case kXenosColorRenderTargetFormat_8_8_8_8_GAMMA:
sample_0 = XeUnpackR8G8B8A8UNorm(packed.x);
sample_1 = XeUnpackR8G8B8A8UNorm(packed.y);
break;
case kXenosColorRenderTargetFormat_2_10_10_10:
case kXenosColorRenderTargetFormat_2_10_10_10_AS_10_10_10_10:
sample_0 = XeUnpackR10G10B10A2UNorm(packed.x);
sample_1 = XeUnpackR10G10B10A2UNorm(packed.y);
break;
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT:
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT_AS_16_16_16_16:
sample_0 = XeUnpackR10G10B10A2Float(packed.x);
sample_1 = XeUnpackR10G10B10A2Float(packed.y);
break;
case kXenosColorRenderTargetFormat_16_16:
sample_0 = xesl_float4(XeUnpackR16G16Edram(packed.x), 0.0f, 0.0f);
sample_1 = xesl_float4(XeUnpackR16G16Edram(packed.y), 0.0f, 0.0f);
break;
case kXenosColorRenderTargetFormat_16_16_FLOAT:
sample_0 = xesl_float4(xesl_unpackHalf2x16(packed.x), 0.0f, 0.0f);
sample_1 = xesl_float4(xesl_unpackHalf2x16(packed.y), 0.0f, 0.0f);
break;
default:
// Treat as 32_FLOAT.
sample_0 = xesl_float2(xesl_uintBitsToFloat(packed.x), 0.0f).xyyy;
sample_1 = xesl_float2(xesl_uintBitsToFloat(packed.y), 0.0f).xyyy;
break;
}
}
void XeResolveUnpack32bpp4Samples(
xesl_uint4 packed, uint format,
xesl_function_param_out(xesl_float4, sample_0),
xesl_function_param_out(xesl_float4, sample_1),
xesl_function_param_out(xesl_float4, sample_2),
xesl_function_param_out(xesl_float4, sample_3)) {
switch (format) {
case kXenosColorRenderTargetFormat_8_8_8_8:
case kXenosColorRenderTargetFormat_8_8_8_8_GAMMA:
sample_0 = XeUnpackR8G8B8A8UNorm(packed.x);
sample_1 = XeUnpackR8G8B8A8UNorm(packed.y);
sample_2 = XeUnpackR8G8B8A8UNorm(packed.z);
sample_3 = XeUnpackR8G8B8A8UNorm(packed.w);
break;
case kXenosColorRenderTargetFormat_2_10_10_10:
case kXenosColorRenderTargetFormat_2_10_10_10_AS_10_10_10_10:
sample_0 = XeUnpackR10G10B10A2UNorm(packed.x);
sample_1 = XeUnpackR10G10B10A2UNorm(packed.y);
sample_2 = XeUnpackR10G10B10A2UNorm(packed.z);
sample_3 = XeUnpackR10G10B10A2UNorm(packed.w);
break;
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT:
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT_AS_16_16_16_16:
sample_0 = XeUnpackR10G10B10A2Float(packed.x);
sample_1 = XeUnpackR10G10B10A2Float(packed.y);
sample_2 = XeUnpackR10G10B10A2Float(packed.z);
sample_3 = XeUnpackR10G10B10A2Float(packed.w);
break;
case kXenosColorRenderTargetFormat_16_16:
sample_0 = xesl_float4(XeUnpackR16G16Edram(packed.x), 0.0f, 0.0f);
sample_1 = xesl_float4(XeUnpackR16G16Edram(packed.y), 0.0f, 0.0f);
sample_2 = xesl_float4(XeUnpackR16G16Edram(packed.z), 0.0f, 0.0f);
sample_3 = xesl_float4(XeUnpackR16G16Edram(packed.w), 0.0f, 0.0f);
break;
case kXenosColorRenderTargetFormat_16_16_FLOAT:
sample_0 = xesl_float4(xesl_unpackHalf2x16(packed.x), 0.0f, 0.0f);
sample_1 = xesl_float4(xesl_unpackHalf2x16(packed.y), 0.0f, 0.0f);
sample_2 = xesl_float4(xesl_unpackHalf2x16(packed.z), 0.0f, 0.0f);
sample_3 = xesl_float4(xesl_unpackHalf2x16(packed.w), 0.0f, 0.0f);
break;
default:
// Treat as 32_FLOAT.
sample_0 = xesl_float2(xesl_uintBitsToFloat(packed.x), 0.0f).xyyy;
sample_1 = xesl_float2(xesl_uintBitsToFloat(packed.y), 0.0f).xyyy;
sample_2 = xesl_float2(xesl_uintBitsToFloat(packed.z), 0.0f).xyyy;
sample_3 = xesl_float2(xesl_uintBitsToFloat(packed.w), 0.0f).xyyy;
break;
}
}
void XeResolveUnpack32bpp8RedSamples(
xesl_uint4 packed_0123, xesl_uint4 packed_4567, uint format, bool swap,
xesl_function_param_out(xesl_float4, samples_0123),
xesl_function_param_out(xesl_float4, samples_4567)) {
switch (format) {
case kXenosColorRenderTargetFormat_8_8_8_8:
case kXenosColorRenderTargetFormat_8_8_8_8_GAMMA: {
uint shift = swap ? 16u : 0u;
samples_0123 = XeUnpackR8UNormX4(packed_0123 >> shift);
samples_4567 = XeUnpackR8UNormX4(packed_4567 >> shift);
} break;
case kXenosColorRenderTargetFormat_2_10_10_10:
case kXenosColorRenderTargetFormat_2_10_10_10_AS_10_10_10_10: {
uint shift = swap ? 20u : 0u;
samples_0123 = XeUnpackR10UNormX4(packed_0123 >> shift);
samples_4567 = XeUnpackR10UNormX4(packed_4567 >> shift);
} break;
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT:
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT_AS_16_16_16_16: {
uint shift = swap ? 20u : 0u;
samples_0123 = XeUnpackR10FloatX4(packed_0123 >> shift);
samples_4567 = XeUnpackR10FloatX4(packed_4567 >> shift);
} break;
case kXenosColorRenderTargetFormat_16_16:
samples_0123 = XeUnpackR16EdramX4(packed_0123);
samples_4567 = XeUnpackR16EdramX4(packed_4567);
break;
case kXenosColorRenderTargetFormat_16_16_FLOAT:
samples_0123.x = xesl_unpackHalf2x16(packed_0123.x).x;
samples_0123.y = xesl_unpackHalf2x16(packed_0123.y).x;
samples_0123.z = xesl_unpackHalf2x16(packed_0123.z).x;
samples_0123.w = xesl_unpackHalf2x16(packed_0123.w).x;
samples_4567.x = xesl_unpackHalf2x16(packed_4567.x).x;
samples_4567.y = xesl_unpackHalf2x16(packed_4567.y).x;
samples_4567.z = xesl_unpackHalf2x16(packed_4567.z).x;
samples_4567.w = xesl_unpackHalf2x16(packed_4567.w).x;
break;
default:
// Treat as 32_FLOAT.
samples_0123 = xesl_uintBitsToFloat(packed_0123);
samples_4567 = xesl_uintBitsToFloat(packed_4567);
break;
}
}
void XeResolveUnpack64bpp2Samples(
xesl_uint4 packed, uint format,
xesl_function_param_out(xesl_float4, sample_0),
xesl_function_param_out(xesl_float4, sample_1)) {
switch (format) {
case kXenosColorRenderTargetFormat_16_16_16_16:
sample_0 = XeUnpackR16G16B16A16Edram(packed.xy);
sample_1 = XeUnpackR16G16B16A16Edram(packed.zw);
break;
case kXenosColorRenderTargetFormat_16_16_16_16_FLOAT:
sample_0.xy = xesl_unpackHalf2x16(packed.x);
sample_0.zw = xesl_unpackHalf2x16(packed.y);
sample_1.xy = xesl_unpackHalf2x16(packed.z);
sample_1.zw = xesl_unpackHalf2x16(packed.w);
break;
default:
// Treat as 32_32_FLOAT.
sample_0 = xesl_float4(xesl_uintBitsToFloat(packed.xy), 0.0f, 0.0f);
sample_1 = xesl_float4(xesl_uintBitsToFloat(packed.zw), 0.0f, 0.0f);
break;
}
}
void XeResolveUnpack64bpp4Samples(
xesl_uint4 packed_01, xesl_uint4 packed_23, uint format,
xesl_function_param_out(xesl_float4, sample_0),
xesl_function_param_out(xesl_float4, sample_1),
xesl_function_param_out(xesl_float4, sample_2),
xesl_function_param_out(xesl_float4, sample_3)) {
switch (format) {
case kXenosColorRenderTargetFormat_16_16_16_16:
sample_0 = XeUnpackR16G16B16A16Edram(packed_01.xy);
sample_1 = XeUnpackR16G16B16A16Edram(packed_01.zw);
sample_2 = XeUnpackR16G16B16A16Edram(packed_23.xy);
sample_3 = XeUnpackR16G16B16A16Edram(packed_23.zw);
break;
case kXenosColorRenderTargetFormat_16_16_16_16_FLOAT:
sample_0.xy = xesl_unpackHalf2x16(packed_01.x);
sample_0.zw = xesl_unpackHalf2x16(packed_01.y);
sample_1.xy = xesl_unpackHalf2x16(packed_01.z);
sample_1.zw = xesl_unpackHalf2x16(packed_01.w);
sample_2.xy = xesl_unpackHalf2x16(packed_23.x);
sample_2.zw = xesl_unpackHalf2x16(packed_23.y);
sample_3.xy = xesl_unpackHalf2x16(packed_23.z);
sample_3.zw = xesl_unpackHalf2x16(packed_23.w);
break;
default:
// Treat as 32_32_FLOAT.
sample_0 = xesl_float4(xesl_uintBitsToFloat(packed_01.xy), 0.0f, 0.0f);
sample_1 = xesl_float4(xesl_uintBitsToFloat(packed_01.zw), 0.0f, 0.0f);
sample_2 = xesl_float4(xesl_uintBitsToFloat(packed_23.xy), 0.0f, 0.0f);
sample_3 = xesl_float4(xesl_uintBitsToFloat(packed_23.zw), 0.0f, 0.0f);
break;
}
}
void XeResolveUnpack64bpp8RedUnswappedSamples(
xesl_uint4 packed_0123, xesl_uint4 packed_4567, uint format,
xesl_function_param_out(xesl_float4, samples_0123),
xesl_function_param_out(xesl_float4, samples_4567)) {
switch (format) {
case kXenosColorRenderTargetFormat_16_16_16_16:
samples_0123 = XeUnpackR16EdramX4(packed_0123);
samples_4567 = XeUnpackR16EdramX4(packed_4567);
break;
case kXenosColorRenderTargetFormat_16_16_16_16_FLOAT:
samples_0123.x = xesl_unpackHalf2x16(packed_0123.x).x;
samples_0123.y = xesl_unpackHalf2x16(packed_0123.y).x;
samples_0123.z = xesl_unpackHalf2x16(packed_0123.z).x;
samples_0123.w = xesl_unpackHalf2x16(packed_0123.w).x;
samples_4567.x = xesl_unpackHalf2x16(packed_4567.x).x;
samples_4567.y = xesl_unpackHalf2x16(packed_4567.y).x;
samples_4567.z = xesl_unpackHalf2x16(packed_4567.z).x;
samples_4567.w = xesl_unpackHalf2x16(packed_4567.w).x;
break;
default:
// Treat as 32_32_FLOAT.
samples_0123 = xesl_uintBitsToFloat(packed_0123);
samples_4567 = xesl_uintBitsToFloat(packed_4567);
break;
}
}
#ifdef XE_RESOLVE_COPY_EDRAM_IS_UINT_VECTOR_BUFFER
void XeResolveLoad2RGBAUnswappedPixelSamplesFromRaw(
xesl_function_param_uintVectorBuffer(xe_resolve_edram)
xesl_function_param_next_after_uintVectorBuffer
uint sample_address_ints, uint pixel_stride_ints, uint format_ints_log2,
uint format, xesl_function_param_out(xesl_float4, pixel_0),
xesl_function_param_out(xesl_float4, pixel_1)) {
xesl_dont_flatten if (format_ints_log2 != 0u) {
xesl_uint4 packed;
xesl_dont_flatten if (pixel_stride_ints == 2u) {
packed = xesl_uintVectorBufferLoad4(
xe_resolve_edram, sample_address_ints);
} else {
packed.xy = xesl_uintVectorBufferLoad2(
xe_resolve_edram, sample_address_ints);
packed.zw = xesl_uintVectorBufferLoad2(
xe_resolve_edram, sample_address_ints + pixel_stride_ints);
}
XeResolveUnpack64bpp2Samples(packed, format, pixel_0, pixel_1);
} else {
xesl_uint2 packed;
xesl_dont_flatten if (pixel_stride_ints == 1u) {
packed = xesl_uintVectorBufferLoad2(
xe_resolve_edram, sample_address_ints);
} else {
packed.x = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints);
packed.y = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + pixel_stride_ints);
}
XeResolveUnpack32bpp2Samples(packed, format, pixel_0, pixel_1);
}
}
void XeResolveLoad4RGBAUnswappedPixelSamplesFromRaw(
xesl_function_param_uintVectorBuffer(xe_resolve_edram)
xesl_function_param_next_after_uintVectorBuffer
uint sample_address_ints, uint pixel_stride_ints, uint format_ints_log2,
uint format, xesl_function_param_out(xesl_float4, pixel_0),
xesl_function_param_out(xesl_float4, pixel_1),
xesl_function_param_out(xesl_float4, pixel_2),
xesl_function_param_out(xesl_float4, pixel_3)) {
xesl_dont_flatten if (format_ints_log2 != 0u) {
xesl_uint4 packed_01, packed_23;
xesl_dont_flatten if (pixel_stride_ints == 2u) {
packed_01 = xesl_uintVectorBufferLoad4(
xe_resolve_edram, sample_address_ints);
packed_23 = xesl_uintVectorBufferLoad4(
xe_resolve_edram, sample_address_ints + 4u);
} else {
packed_01.xy = xesl_uintVectorBufferLoad2(
xe_resolve_edram, sample_address_ints);
packed_01.zw = xesl_uintVectorBufferLoad2(
xe_resolve_edram, sample_address_ints + pixel_stride_ints);
packed_23.xy = xesl_uintVectorBufferLoad2(
xe_resolve_edram, sample_address_ints + 2u * pixel_stride_ints);
packed_23.zw = xesl_uintVectorBufferLoad2(
xe_resolve_edram, sample_address_ints + 3u * pixel_stride_ints);
}
XeResolveUnpack64bpp4Samples(packed_01, packed_23, format, pixel_0,
pixel_1, pixel_2, pixel_3);
} else {
xesl_uint4 packed;
xesl_dont_flatten if (pixel_stride_ints == 1u) {
packed = xesl_uintVectorBufferLoad4(
xe_resolve_edram, sample_address_ints);
} else {
packed.x = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints);
packed.y = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + pixel_stride_ints);
packed.z = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 2u * pixel_stride_ints);
packed.w = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 3u * pixel_stride_ints);
}
XeResolveUnpack32bpp4Samples(packed, format, pixel_0, pixel_1, pixel_2,
pixel_3);
}
}
// For red/blue swapping for 64bpp, pre-add 1 to sample_address_ints.
void XeResolveLoad8RedPixelSamplesFromRaw(
xesl_function_param_uintVectorBuffer(xe_resolve_edram)
xesl_function_param_next_after_uintVectorBuffer
uint sample_address_ints, uint pixel_stride_ints, uint format_ints_log2,
uint format, bool swap_32bpp,
xesl_function_param_out(xesl_float4, pixels_0123),
xesl_function_param_out(xesl_float4, pixels_4567)) {
xesl_uint4 packed_0123, packed_4567;
xesl_dont_flatten if (pixel_stride_ints == 1u) {
packed_0123 = xesl_uintVectorBufferLoad4(
xe_resolve_edram, sample_address_ints);
packed_4567 = xesl_uintVectorBufferLoad4(
xe_resolve_edram, sample_address_ints + 4u);
} else {
packed_0123.x = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints);
packed_0123.y = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + pixel_stride_ints);
packed_0123.z = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 2u * pixel_stride_ints);
packed_0123.w = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 3u * pixel_stride_ints);
packed_4567.x = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 4u * pixel_stride_ints);
packed_4567.y = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 5u * pixel_stride_ints);
packed_4567.z = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 6u * pixel_stride_ints);
packed_4567.w = xesl_uintVectorBufferLoad1(
xe_resolve_edram, sample_address_ints + 7u * pixel_stride_ints);
}
xesl_dont_flatten if (format_ints_log2 != 0u) {
XeResolveUnpack64bpp8RedUnswappedSamples(packed_0123, packed_4567,
format, pixels_0123,
pixels_4567);
} else {
XeResolveUnpack32bpp8RedSamples(packed_0123, packed_4567, format,
swap_32bpp, pixels_0123, pixels_4567);
}
}
void XeResolveLoad2RGBAColors(
xesl_function_param_uintVectorBuffer(xe_resolve_edram)
xesl_function_param_next_after_uintVectorBuffer
XeResolveInfo resolve_info, uint address_ints,
xesl_function_param_out(xesl_float4, pixel_0),
xesl_function_param_out(xesl_float4, pixel_1)) {
uint pixel_stride_ints = XeResolveEdramPixelStrideInts(resolve_info);
XeResolveLoad2RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints, pixel_stride_ints, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, pixel_0, pixel_1);
float exp_bias = resolve_info.dest_exp_bias_factor;
xesl_dont_flatten
if (resolve_info.sample_select >= kXenosCopySampleSelect_01) {
uint tile_row_stride_ints = 80u * resolve_info.resolution_scale.x;
// TODO(Triang3l): Gamma-correct resolve for 8_8_8_8_GAMMA.
exp_bias *= 0.5f;
xesl_float4 msaa_resolve_pixel_0, msaa_resolve_pixel_1;
XeResolveLoad2RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + tile_row_stride_ints, pixel_stride_ints,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
xesl_dont_flatten
if (resolve_info.sample_select >= kXenosCopySampleSelect_0123) {
uint sample_stride_ints = 1u << resolve_info.edram_format_ints_log2;
exp_bias *= 0.5f;
XeResolveLoad2RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + sample_stride_ints, pixel_stride_ints,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
XeResolveLoad2RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + tile_row_stride_ints + sample_stride_ints,
pixel_stride_ints, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, msaa_resolve_pixel_0,
msaa_resolve_pixel_1);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
}
}
pixel_0 *= exp_bias;
pixel_1 *= exp_bias;
xesl_dont_flatten if (resolve_info.dest_swap) {
pixel_0 = pixel_0.bgra;
pixel_1 = pixel_1.bgra;
}
}
void XeResolveLoad4RGBAColors(
xesl_function_param_uintVectorBuffer(xe_resolve_edram)
xesl_function_param_next_after_uintVectorBuffer
XeResolveInfo resolve_info, uint address_ints,
xesl_function_param_out(xesl_float4, pixel_0),
xesl_function_param_out(xesl_float4, pixel_1),
xesl_function_param_out(xesl_float4, pixel_2),
xesl_function_param_out(xesl_float4, pixel_3)) {
uint pixel_stride_ints = XeResolveEdramPixelStrideInts(resolve_info);
XeResolveLoad4RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints, pixel_stride_ints, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, pixel_0, pixel_1, pixel_2, pixel_3);
float exp_bias = resolve_info.dest_exp_bias_factor;
xesl_dont_flatten
if (resolve_info.sample_select >= kXenosCopySampleSelect_01) {
uint tile_row_stride_ints = 80u * resolve_info.resolution_scale.x;
// TODO(Triang3l): Gamma-correct resolve for 8_8_8_8_GAMMA.
exp_bias *= 0.5f;
xesl_float4 msaa_resolve_pixel_0;
xesl_float4 msaa_resolve_pixel_1;
xesl_float4 msaa_resolve_pixel_2;
xesl_float4 msaa_resolve_pixel_3;
XeResolveLoad4RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + tile_row_stride_ints, pixel_stride_ints,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1, msaa_resolve_pixel_2,
msaa_resolve_pixel_3);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
pixel_2 += msaa_resolve_pixel_2;
pixel_3 += msaa_resolve_pixel_3;
xesl_dont_flatten
if (resolve_info.sample_select >= kXenosCopySampleSelect_0123) {
uint sample_stride_ints = 1u << resolve_info.edram_format_ints_log2;
exp_bias *= 0.5f;
XeResolveLoad4RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + sample_stride_ints, pixel_stride_ints,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
msaa_resolve_pixel_0, msaa_resolve_pixel_1, msaa_resolve_pixel_2,
msaa_resolve_pixel_3);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
pixel_2 += msaa_resolve_pixel_2;
pixel_3 += msaa_resolve_pixel_3;
XeResolveLoad4RGBAUnswappedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + tile_row_stride_ints + sample_stride_ints,
pixel_stride_ints, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, msaa_resolve_pixel_0,
msaa_resolve_pixel_1, msaa_resolve_pixel_2, msaa_resolve_pixel_3);
pixel_0 += msaa_resolve_pixel_0;
pixel_1 += msaa_resolve_pixel_1;
pixel_2 += msaa_resolve_pixel_2;
pixel_3 += msaa_resolve_pixel_3;
}
}
pixel_0 *= exp_bias;
pixel_1 *= exp_bias;
pixel_2 *= exp_bias;
pixel_3 *= exp_bias;
xesl_dont_flatten if (resolve_info.dest_swap) {
pixel_0 = pixel_0.bgra;
pixel_1 = pixel_1.bgra;
pixel_2 = pixel_2.bgra;
pixel_3 = pixel_3.bgra;
}
}
void XeResolveLoad8RedColors(
xesl_function_param_uintVectorBuffer(xe_resolve_edram)
xesl_function_param_next_after_uintVectorBuffer
XeResolveInfo resolve_info, uint address_ints,
xesl_function_param_out(xesl_float4, pixels_0123),
xesl_function_param_out(xesl_float4, pixels_4567)) {
uint pixel_stride_ints = XeResolveEdramPixelStrideInts(resolve_info);
if (resolve_info.dest_swap) {
// Likely want to load the blue part from the right half for 64bpp.
address_ints += resolve_info.edram_format_ints_log2;
}
XeResolveLoad8RedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints, pixel_stride_ints, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, resolve_info.dest_swap, pixels_0123,
pixels_4567);
float exp_bias = resolve_info.dest_exp_bias_factor;
xesl_dont_flatten
if (resolve_info.sample_select >= kXenosCopySampleSelect_01) {
uint tile_row_stride_ints = 80u * resolve_info.resolution_scale.x;
// TODO(Triang3l): Gamma-correct resolve for 8_8_8_8_GAMMA.
exp_bias *= 0.5f;
xesl_float4 msaa_resolve_pixels_0123, msaa_resolve_pixels_4567;
XeResolveLoad8RedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + tile_row_stride_ints, pixel_stride_ints,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
resolve_info.dest_swap, msaa_resolve_pixels_0123,
msaa_resolve_pixels_4567);
pixels_0123 += msaa_resolve_pixels_0123;
pixels_4567 += msaa_resolve_pixels_4567;
xesl_dont_flatten
if (resolve_info.sample_select >= kXenosCopySampleSelect_0123) {
uint sample_stride_ints = 1u << resolve_info.edram_format_ints_log2;
exp_bias *= 0.5f;
XeResolveLoad8RedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + sample_stride_ints, pixel_stride_ints,
resolve_info.edram_format_ints_log2, resolve_info.edram_format,
resolve_info.dest_swap, msaa_resolve_pixels_0123,
msaa_resolve_pixels_4567);
pixels_0123 += msaa_resolve_pixels_0123;
pixels_4567 += msaa_resolve_pixels_4567;
XeResolveLoad8RedPixelSamplesFromRaw(
xesl_function_call_uintVectorBuffer(xe_resolve_edram)
xesl_function_call_next_after_uintVectorBuffer
address_ints + tile_row_stride_ints + sample_stride_ints,
pixel_stride_ints, resolve_info.edram_format_ints_log2,
resolve_info.edram_format, resolve_info.dest_swap,
msaa_resolve_pixels_0123, msaa_resolve_pixels_4567);
pixels_0123 += msaa_resolve_pixels_0123;
pixels_4567 += msaa_resolve_pixels_4567;
}
}
pixels_0123 *= exp_bias;
pixels_4567 *= exp_bias;
}
#endif // XE_RESOLVE_COPY_EDRAM_IS_UINT_VECTOR_BUFFER
xesl_uint4 XeResolveSwapRedBlue_8_8_8_8(xesl_uint4 pixels) {
return (pixels & ~0xFF00FFu) | ((pixels & 0xFFu) << 16u) |
((pixels >> 16u) & 0xFFu);
}
xesl_uint4 XeResolveSwapRedBlue_2_10_10_10(xesl_uint4 pixels) {
return (pixels & ~0x3FF003FF) | ((pixels & 0x3FFu) << 20u) |
((pixels >> 20u) & 0x3FFu);
}
void XeResolveSwap8PixelsRedBlue32bpp(
XeResolveInfo resolve_info,
xesl_function_param_inout(xesl_uint4, pixels_0123),
xesl_function_param_inout(xesl_uint4, pixels_4567)) {
xesl_dont_flatten if (resolve_info.dest_swap) {
switch (resolve_info.edram_format) {
case kXenosColorRenderTargetFormat_8_8_8_8:
case kXenosColorRenderTargetFormat_8_8_8_8_GAMMA:
pixels_0123 = XeResolveSwapRedBlue_8_8_8_8(pixels_0123);
pixels_4567 = XeResolveSwapRedBlue_8_8_8_8(pixels_4567);
break;
case kXenosColorRenderTargetFormat_2_10_10_10:
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT:
case kXenosColorRenderTargetFormat_2_10_10_10_AS_10_10_10_10:
case kXenosColorRenderTargetFormat_2_10_10_10_FLOAT_AS_16_16_16_16:
pixels_0123 = XeResolveSwapRedBlue_2_10_10_10(pixels_0123);
pixels_4567 = XeResolveSwapRedBlue_2_10_10_10(pixels_4567);
break;
}
}
}
void XeResolveSwap4PixelsRedBlue64bpp(
XeResolveInfo resolve_info,
xesl_function_param_inout(xesl_uint4, pixels_01),
xesl_function_param_inout(xesl_uint4, pixels_23)) {
xesl_dont_flatten if (resolve_info.dest_swap) {
xesl_dont_flatten
if (resolve_info.edram_format ==
kXenosColorRenderTargetFormat_16_16_16_16 ||
resolve_info.edram_format ==
kXenosColorRenderTargetFormat_16_16_16_16_FLOAT) {
pixels_01 = (pixels_01 & ~0xFFFFu) | (pixels_01.yxwz & 0xFFFFu);
pixels_23 = (pixels_23 & ~0xFFFFu) | (pixels_23.yxwz & 0xFFFFu);
}
}
}
#endif
#endif // XENIA_GPU_SHADERS_RESOLVE_XESLI_