/** ****************************************************************************** * 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 XeEdramOffsetInts(xesl_uint2 pixel_index, uint base_tiles, bool wrap, uint pitch_tiles, uint msaa_samples, bool is_depth, uint format_ints_log2, uint pixel_sample_index, xesl_uint2 resolution_scale) { xesl_uint2 rt_sample_index = pixel_index << xesl_uint2(xesl_greaterThanEqual( xesl_uint_x2(msaa_samples), xesl_uint2(kXenosMsaaSamples_4X, kXenosMsaaSamples_2X))); rt_sample_index += (xesl_uint_x2(pixel_sample_index) >> xesl_uint2(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. xesl_uint2 tile_size_at_32bpp = xesl_uint2(80u, 16u) * resolution_scale; xesl_uint2 tile_size_samples = tile_size_at_32bpp >> xesl_uint2(format_ints_log2, 0u); xesl_uint2 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; } #endif // XENIA_GPU_SHADERS_EDRAM_XESLI_