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.
61 lines
2.7 KiB
Plaintext
61 lines
2.7 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_EDRAM_XESLI_
|
|
#define XENIA_GPU_SHADERS_EDRAM_XESLI_
|
|
|
|
#include "pixel_formats.xesli"
|
|
|
|
#define kXenosMsaaSamples_1X 0u
|
|
#define kXenosMsaaSamples_2X 1u
|
|
#define kXenosMsaaSamples_4X 2u
|
|
|
|
// `wrap = false` can be used if it's known that the resulting tile indices
|
|
// can't exceed 11 bits, and the modulo operator doesn't need to be performed to
|
|
// access the data in the render targets that are located in both ends of the
|
|
// EDRAM at the same time.
|
|
uint XeEdramOffsetBytes(uint2_xe pixel_index, uint base_tiles, bool wrap,
|
|
uint pitch_tiles, uint msaa_samples, bool is_depth,
|
|
uint format_ints_log2, uint pixel_sample_index,
|
|
uint2_xe resolution_scale) {
|
|
uint2_xe rt_sample_index =
|
|
pixel_index <<
|
|
uint2_xe(greater_than_equal_xe(
|
|
uint_x2_xe(msaa_samples),
|
|
uint2_xe(kXenosMsaaSamples_4X, kXenosMsaaSamples_2X)));
|
|
rt_sample_index += (uint_x2_xe(pixel_sample_index) >> uint2_xe(1u, 0u)) & 1u;
|
|
// For now, while the actual storage of 64bpp render targets in comparison to
|
|
// 32bpp is not known, storing 40x16 64bpp samples per tile for simplicity of
|
|
// addressing in different scenarios.
|
|
uint2_xe tile_size_at_32bpp = uint2_xe(80u, 16u) * resolution_scale;
|
|
uint2_xe tile_size_samples =
|
|
tile_size_at_32bpp >> uint2_xe(format_ints_log2, 0u);
|
|
uint2_xe tile_offset_xy = rt_sample_index / tile_size_samples;
|
|
base_tiles += tile_offset_xy.y * pitch_tiles + tile_offset_xy.x;
|
|
rt_sample_index -= tile_offset_xy * tile_size_samples;
|
|
if (is_depth) {
|
|
uint tile_width_half = tile_size_samples.x >> 1u;
|
|
rt_sample_index.x =
|
|
uint(int(rt_sample_index.x) +
|
|
((rt_sample_index.x >= tile_width_half) ? -int(tile_width_half)
|
|
: int(tile_width_half)));
|
|
}
|
|
uint address =
|
|
base_tiles * (tile_size_at_32bpp.x * tile_size_at_32bpp.y) +
|
|
((rt_sample_index.y * tile_size_samples.x + rt_sample_index.x) <<
|
|
format_ints_log2);
|
|
if (wrap) {
|
|
// EDRAM addressing is periodic (modulo the EDRAM size).
|
|
address %= tile_size_at_32bpp.x * tile_size_at_32bpp.y * 2048u;
|
|
}
|
|
return address << 2;
|
|
}
|
|
|
|
#endif // XENIA_GPU_SHADERS_EDRAM_XESLI_
|