Drivers and hardware may provide more optimal paths for untyped buffers compared to typed. Also, ByteAddressBuffer may be bound via a root descriptor in Direct3D 12, greatly simplifying the binding logic. ByteAddressBuffer also doesn't have the 128 * 2^20 element count limit that typed and structured buffers have, and doesn't require the structure stride to be specified at resource creation time in Direct3D 11.
69 lines
2.9 KiB
Plaintext
69 lines
2.9 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. *
|
|
******************************************************************************
|
|
*/
|
|
|
|
#include "endian.xesli"
|
|
#define XE_RESOLVE_COPY_EDRAM_BYTE_BUFFER_ALIGNMENT 4
|
|
#include "resolve.xesli"
|
|
|
|
byte_buffer_align16_wo_declare_xe(xe_resolve_dest, set=1, binding=0, u0, space0)
|
|
#define LOCAL_SIZE_X_XE 8
|
|
#define LOCAL_SIZE_Y_XE 8
|
|
#define LOCAL_SIZE_Z_XE 1
|
|
entry_bindings_begin_compute_xe
|
|
XE_RESOLVE_PUSH_CONST_BINDING
|
|
entry_binding_next_xe
|
|
byte_buffer_wo_binding_xe(xe_resolve_dest, buffer(1))
|
|
entry_binding_next_xe
|
|
XE_RESOLVE_COPY_EDRAM_BINDING
|
|
entry_bindings_end_inputs_begin_compute_xe
|
|
entry_in_global_thread_id_xe
|
|
entry_inputs_end_code_begin_compute_xe
|
|
{
|
|
// 1 thread = 2 host pixels.
|
|
XeResolveInfo resolve_info = XeResolveGetInfo(pass_push_consts_xe);
|
|
uint2_xe pixel_index = in_global_thread_id_xe.xy << uint2_xe(1u, 0u);
|
|
// Group height can't cross resolve granularity, Y overflow check not needed.
|
|
dont_flatten_xe
|
|
if (pixel_index.x >= resolve_info.width_div_8_scaled << 3u) {
|
|
return;
|
|
}
|
|
float4_xe pixel_0, pixel_1;
|
|
XeResolveLoad2RGBAColors(
|
|
pass_byte_buffer_xe(xe_resolve_edram) pass_next_after_byte_buffer_xe
|
|
resolve_info,
|
|
XeResolveColorCopySourcePixelAddressBytesYHalfPixelOffsetFilling(
|
|
resolve_info,
|
|
uint2_xe(max(pixel_index.x,
|
|
resolve_info.half_pixel_offset_fill_source.x),
|
|
pixel_index.y)),
|
|
pixel_0, pixel_1);
|
|
// Inside the half-pixel offset filling columns, pixel_0 now contains the
|
|
// pixel to stretch, pixel_1 contains the pixel after it. However, this means
|
|
// that the pixel offset is not aligned to 2 anymore. If 1 is the pixel to
|
|
// stretch, the two pixels will be 1 and 2 for pixel_index.x == 0. If 3 is,
|
|
// they will be 3 and 4 for pixel_index.x == 0 and 2. However, in the former
|
|
// case, they should be 1 and 1, and in the latter, 3 and 3.
|
|
dont_flatten_xe
|
|
if (pixel_index.x < resolve_info.half_pixel_offset_fill_source.x) {
|
|
pixel_1 = pixel_0;
|
|
}
|
|
// Only 32_32_32_32_FLOAT color format is 128bpp.
|
|
uint dest_address = XeResolveDestPixelAddress(resolve_info, pixel_index, 4u);
|
|
byte_buffer_align16_store16_xe(
|
|
xe_resolve_dest, dest_address,
|
|
XeEndianSwap128(float_bits_to_uint_xe(pixel_0),
|
|
resolve_info.dest_endian_128));
|
|
dest_address += XeResolveLocalXAddressXor(1u, 4u);
|
|
byte_buffer_align16_store16_xe(
|
|
xe_resolve_dest, dest_address,
|
|
XeEndianSwap128(float_bits_to_uint_xe(pixel_1),
|
|
resolve_info.dest_endian_128));
|
|
}
|
|
entry_code_end_compute_xe
|