Refactor graphics #1

This commit is contained in:
nmzik
2026-07-19 00:54:31 +02:00
parent 7905f2d12f
commit cbc11d2eaf
71 changed files with 2051 additions and 3399 deletions
+71 -361
View File
@@ -1392,81 +1392,82 @@ static const Standard64KB128Tables& GetStandard64KB128Tables() {
return tables;
}
void TileConvertTiledToLinearStandard64KB32(void* dst, const void* src, uint32_t width,
uint32_t height, uint32_t pitch, uint64_t size,
uint64_t src_size, uint32_t src_x, uint32_t src_y) {
KYTY_PROFILER_FUNCTION();
template <typename T, uint32_t BlockWidth, uint32_t BlockHeight, uint32_t CopyBatch,
bool ExactSurfaceRequiresFullWidth, typename Tables>
static void ConvertTiledToLinearStandard64KBElements(void* dst, const void* src, uint32_t width,
uint32_t height, uint32_t pitch, uint64_t size,
uint64_t src_size, uint32_t src_x,
uint32_t src_y, const Tables& tables) {
static_assert(BlockWidth * BlockHeight * sizeof(T) == 64u * 1024u);
static_assert(CopyBatch != 0 && BlockWidth % CopyBatch == 0);
EXIT_IF(dst == nullptr || src == nullptr);
EXIT_NOT_IMPLEMENTED(pitch == 0);
const bool tail_block = (src_size != 0 && (src_x != 0 || src_y != 0 || size < src_size));
EXIT_NOT_IMPLEMENTED(width > pitch);
EXIT_NOT_IMPLEMENTED(tail_block && (src_x + width > 128u || src_y + height > 128u));
EXIT_NOT_IMPLEMENTED(tail_block &&
(src_x + width > BlockWidth || src_y + height > BlockHeight));
auto* dst32 = static_cast<uint32_t*>(dst);
const auto* src32 = static_cast<const uint32_t*>(src);
const auto& tables = GetStandard64KB32Tables();
const auto size_words = size >> 2u;
const auto src_size_words = (src_size != 0 ? src_size : size) >> 2u;
auto* dst_elements = static_cast<T*>(dst);
const auto* src_elements = static_cast<const T*>(src);
const auto element_count = size / sizeof(T);
const auto src_element_count = (src_size != 0 ? src_size : size) / sizeof(T);
const auto blocks_per_row =
(tail_block ? 1u : static_cast<uint64_t>(AlignUp(pitch, 128u) >> 7u));
const auto dst_words = static_cast<uint64_t>(pitch) * height;
const bool exact_surface =
(!tail_block && width == pitch && (size & 3u) == 0 && size_words == dst_words);
const auto* x_words = tables.x_words.data();
const auto* y_words = tables.y_words.data();
tail_block ? 1u : static_cast<uint64_t>(AlignUp(pitch, BlockWidth) / BlockWidth);
const auto dst_element_count = static_cast<uint64_t>(pitch) * height;
const bool exact_surface = !tail_block && (!ExactSurfaceRequiresFullWidth || width == pitch) &&
size % sizeof(T) == 0 && element_count == dst_element_count;
const auto* x_elements = tables.x_words.data();
const auto* y_elements = tables.y_words.data();
if (!exact_surface) {
std::memset(dst32, 0, static_cast<size_t>(size));
std::memset(dst_elements, 0, static_cast<size_t>(size));
}
for (uint32_t block_y = 0; block_y < height; block_y += 128u) {
const uint32_t block_height = std::min(128u, height - block_y);
constexpr uint64_t ElementsPerBlock = BlockWidth * BlockHeight;
for (uint32_t block_y = 0; block_y < height; block_y += BlockHeight) {
const uint32_t copy_height = std::min(BlockHeight, height - block_y);
for (uint32_t block_x = 0; block_x < width; block_x += 128u) {
const uint32_t block_width = std::min(128u, width - block_x);
for (uint32_t block_x = 0; block_x < width; block_x += BlockWidth) {
const uint32_t copy_width = std::min(BlockWidth, width - block_x);
const uint64_t block_base =
(tail_block
? 0u
: (((static_cast<uint64_t>(block_y) >> 7u) * blocks_per_row) + (block_x >> 7u))
<< 14u);
const bool full_block =
(!tail_block && block_width == 128u && block_height == 128u &&
block_base + 16384u <= src_size_words &&
(static_cast<uint64_t>(block_y + 127u) * pitch) + block_x + 127u < size_words);
tail_block ? 0u
: ((static_cast<uint64_t>(block_y / BlockHeight) * blocks_per_row) +
block_x / BlockWidth) *
ElementsPerBlock;
const bool full_block = !tail_block && copy_width == BlockWidth &&
copy_height == BlockHeight &&
block_base + ElementsPerBlock <= src_element_count &&
static_cast<uint64_t>(block_y + BlockHeight - 1u) * pitch +
block_x + BlockWidth - 1u <
element_count;
if (full_block) {
for (uint32_t local_y = 0; local_y < 128u; local_y++) {
for (uint32_t local_y = 0; local_y < BlockHeight; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
static_cast<uint64_t>(block_y + local_y) * pitch + block_x;
const uint64_t src_row = block_base + y_elements[src_y + local_y];
for (uint32_t local_x = 0; local_x < 128u; local_x += 4u) {
dst32[dst_row + local_x + 0u] =
src32[src_row + x_words[src_x + local_x + 0u]];
dst32[dst_row + local_x + 1u] =
src32[src_row + x_words[src_x + local_x + 1u]];
dst32[dst_row + local_x + 2u] =
src32[src_row + x_words[src_x + local_x + 2u]];
dst32[dst_row + local_x + 3u] =
src32[src_row + x_words[src_x + local_x + 3u]];
for (uint32_t local_x = 0; local_x < BlockWidth; local_x += CopyBatch) {
for (uint32_t i = 0; i < CopyBatch; i++) {
dst_elements[dst_row + local_x + i] =
src_elements[src_row + x_elements[src_x + local_x + i]];
}
}
}
continue;
}
for (uint32_t local_y = 0; local_y < block_height; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_y = 0; local_y < copy_height; local_y++) {
const uint64_t dst_row = static_cast<uint64_t>(block_y + local_y) * pitch + block_x;
const uint64_t src_row = block_base + y_elements[src_y + local_y];
for (uint32_t local_x = 0; local_x < block_width; local_x++) {
for (uint32_t local_x = 0; local_x < copy_width; local_x++) {
const uint64_t dst_index = dst_row + local_x;
const uint64_t src_index = src_row + x_words[src_x + local_x];
const uint64_t src_index = src_row + x_elements[src_x + local_x];
if (src_index < src_size_words && dst_index < size_words) {
dst32[dst_index] = src32[src_index];
if (src_index < src_element_count && dst_index < element_count) {
dst_elements[dst_index] = src_elements[src_index];
}
}
}
@@ -1474,6 +1475,15 @@ void TileConvertTiledToLinearStandard64KB32(void* dst, const void* src, uint32_t
}
}
void TileConvertTiledToLinearStandard64KB32(void* dst, const void* src, uint32_t width,
uint32_t height, uint32_t pitch, uint64_t size,
uint64_t src_size, uint32_t src_x, uint32_t src_y) {
KYTY_PROFILER_FUNCTION();
ConvertTiledToLinearStandard64KBElements<uint32_t, 128u, 128u, 4u, true>(
dst, src, width, height, pitch, size, src_size, src_x, src_y, GetStandard64KB32Tables());
}
void TileConvertLinearToTiledStandard64KB32(void* dst, const void* src, uint32_t width,
uint32_t height, uint32_t pitch, uint64_t size) {
KYTY_PROFILER_FUNCTION();
@@ -1540,81 +1550,8 @@ void TileConvertTiledToLinearStandard64KB16(void* dst, const void* src, uint32_t
uint64_t src_size, uint32_t src_x, uint32_t src_y) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(dst == nullptr || src == nullptr);
EXIT_NOT_IMPLEMENTED(pitch == 0);
const bool tail_block = (src_size != 0 && (src_x != 0 || src_y != 0 || size < src_size));
EXIT_NOT_IMPLEMENTED(width > pitch);
EXIT_NOT_IMPLEMENTED(tail_block && (src_x + width > 256u || src_y + height > 128u));
auto* dst16 = static_cast<uint16_t*>(dst);
const auto* src16 = static_cast<const uint16_t*>(src);
const auto& tables = GetStandard64KB16Tables();
const auto size_words = size >> 1u;
const auto src_size_words = (src_size != 0 ? src_size : size) >> 1u;
const auto blocks_per_row =
(tail_block ? 1u : static_cast<uint64_t>(AlignUp(pitch, 256u) >> 8u));
const auto dst_words = static_cast<uint64_t>(pitch) * height;
const bool exact_surface =
(!tail_block && width == pitch && (size & 1u) == 0 && size_words == dst_words);
const auto* x_words = tables.x_words.data();
const auto* y_words = tables.y_words.data();
if (!exact_surface) {
std::memset(dst16, 0, static_cast<size_t>(size));
}
for (uint32_t block_y = 0; block_y < height; block_y += 128u) {
const uint32_t block_height = std::min(128u, height - block_y);
for (uint32_t block_x = 0; block_x < width; block_x += 256u) {
const uint32_t block_width = std::min(256u, width - block_x);
const uint64_t block_base =
(tail_block
? 0u
: (((static_cast<uint64_t>(block_y) >> 7u) * blocks_per_row) + (block_x >> 8u))
<< 15u);
const bool full_block =
(!tail_block && block_width == 256u && block_height == 128u &&
block_base + 32768u <= src_size_words &&
(static_cast<uint64_t>(block_y + 127u) * pitch) + block_x + 255u < size_words);
if (full_block) {
for (uint32_t local_y = 0; local_y < 128u; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < 256u; local_x += 4u) {
dst16[dst_row + local_x + 0u] =
src16[src_row + x_words[src_x + local_x + 0u]];
dst16[dst_row + local_x + 1u] =
src16[src_row + x_words[src_x + local_x + 1u]];
dst16[dst_row + local_x + 2u] =
src16[src_row + x_words[src_x + local_x + 2u]];
dst16[dst_row + local_x + 3u] =
src16[src_row + x_words[src_x + local_x + 3u]];
}
}
continue;
}
for (uint32_t local_y = 0; local_y < block_height; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < block_width; local_x++) {
const uint64_t dst_index = dst_row + local_x;
const uint64_t src_index = src_row + x_words[src_x + local_x];
if (src_index < src_size_words && dst_index < size_words) {
dst16[dst_index] = src16[src_index];
}
}
}
}
}
ConvertTiledToLinearStandard64KBElements<uint16_t, 256u, 128u, 4u, true>(
dst, src, width, height, pitch, size, src_size, src_x, src_y, GetStandard64KB16Tables());
}
static void TileConvertTiledToLinearStandard64KB8Elements(
@@ -1622,82 +1559,9 @@ static void TileConvertTiledToLinearStandard64KB8Elements(
uint32_t pitch_elements, uint64_t size, uint64_t src_size, uint32_t src_x, uint32_t src_y) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(dst == nullptr || src == nullptr);
EXIT_NOT_IMPLEMENTED(pitch_elements == 0);
const bool tail_block = (src_size != 0 && (src_x != 0 || src_y != 0 || size < src_size));
EXIT_NOT_IMPLEMENTED(width_elements > pitch_elements);
EXIT_NOT_IMPLEMENTED(tail_block &&
(src_x + width_elements > 256u || src_y + height_elements > 256u));
auto* dst8 = static_cast<uint8_t*>(dst);
const auto* src8 = static_cast<const uint8_t*>(src);
const auto& tables = GetStandard64KB8Tables();
const auto size_words = size;
const auto src_size_words = (src_size != 0 ? src_size : size);
const auto blocks_per_row =
(tail_block ? 1u : static_cast<uint64_t>(AlignUp(pitch_elements, 256u) >> 8u));
const auto dst_words = static_cast<uint64_t>(pitch_elements) * height_elements;
const bool exact_surface = (!tail_block && size_words == dst_words);
const auto* x_words = tables.x_words.data();
const auto* y_words = tables.y_words.data();
if (!exact_surface) {
std::memset(dst8, 0, static_cast<size_t>(size));
}
for (uint32_t block_y = 0; block_y < height_elements; block_y += 256u) {
const uint32_t block_height = std::min(256u, height_elements - block_y);
for (uint32_t block_x = 0; block_x < width_elements; block_x += 256u) {
const uint32_t block_width = std::min(256u, width_elements - block_x);
const uint64_t block_base =
(tail_block
? 0u
: (((static_cast<uint64_t>(block_y) >> 8u) * blocks_per_row) + (block_x >> 8u))
<< 16u);
const bool full_block =
(!tail_block && block_width == 256u && block_height == 256u &&
block_base + 65536u <= src_size_words &&
(static_cast<uint64_t>(block_y + 255u) * pitch_elements) + block_x + 255u <
size_words);
if (full_block) {
for (uint32_t local_y = 0; local_y < 256u; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch_elements) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < 256u; local_x += 4u) {
dst8[dst_row + local_x + 0u] =
src8[src_row + x_words[src_x + local_x + 0u]];
dst8[dst_row + local_x + 1u] =
src8[src_row + x_words[src_x + local_x + 1u]];
dst8[dst_row + local_x + 2u] =
src8[src_row + x_words[src_x + local_x + 2u]];
dst8[dst_row + local_x + 3u] =
src8[src_row + x_words[src_x + local_x + 3u]];
}
}
continue;
}
for (uint32_t local_y = 0; local_y < block_height; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch_elements) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < block_width; local_x++) {
const uint64_t dst_index = dst_row + local_x;
const uint64_t src_index = src_row + x_words[src_x + local_x];
if (src_index < src_size_words && dst_index < size_words) {
dst8[dst_index] = src8[src_index];
}
}
}
}
}
ConvertTiledToLinearStandard64KBElements<uint8_t, 256u, 256u, 4u, false>(
dst, src, width_elements, height_elements, pitch_elements, size, src_size, src_x, src_y,
GetStandard64KB8Tables());
}
static void TileConvertTiledToLinearStandard64KB64Elements(
@@ -1705,90 +1569,9 @@ static void TileConvertTiledToLinearStandard64KB64Elements(
uint32_t pitch_elements, uint64_t size, uint64_t src_size, uint32_t src_x, uint32_t src_y) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(dst == nullptr || src == nullptr);
EXIT_NOT_IMPLEMENTED(pitch_elements == 0);
const bool tail_block = (src_size != 0 && (src_x != 0 || src_y != 0 || size < src_size));
EXIT_NOT_IMPLEMENTED(width_elements > pitch_elements);
EXIT_NOT_IMPLEMENTED(tail_block &&
(src_x + width_elements > 128u || src_y + height_elements > 64u));
auto* dst64 = static_cast<uint64_t*>(dst);
const auto* src64 = static_cast<const uint64_t*>(src);
const auto& tables = GetStandard64KB64Tables();
const auto size_words = size >> 3u;
const auto src_size_words = (src_size != 0 ? src_size : size) >> 3u;
const auto blocks_per_row =
(tail_block ? 1u : static_cast<uint64_t>(AlignUp(pitch_elements, 128u) >> 7u));
const auto dst_words = static_cast<uint64_t>(pitch_elements) * height_elements;
const bool exact_surface = (!tail_block && (size & 7u) == 0 && size_words == dst_words);
const auto* x_words = tables.x_words.data();
const auto* y_words = tables.y_words.data();
if (!exact_surface) {
std::memset(dst64, 0, static_cast<size_t>(size));
}
for (uint32_t block_y = 0; block_y < height_elements; block_y += 64u) {
const uint32_t block_height = std::min(64u, height_elements - block_y);
for (uint32_t block_x = 0; block_x < width_elements; block_x += 128u) {
const uint32_t block_width = std::min(128u, width_elements - block_x);
const uint64_t block_base =
(tail_block
? 0u
: (((static_cast<uint64_t>(block_y) >> 6u) * blocks_per_row) + (block_x >> 7u))
<< 13u);
const bool full_block =
(!tail_block && block_width == 128u && block_height == 64u &&
block_base + 8192u <= src_size_words &&
(static_cast<uint64_t>(block_y + 63u) * pitch_elements) + block_x + 127u <
size_words);
if (full_block) {
for (uint32_t local_y = 0; local_y < 64u; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch_elements) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < 128u; local_x += 8u) {
dst64[dst_row + local_x + 0u] =
src64[src_row + x_words[src_x + local_x + 0u]];
dst64[dst_row + local_x + 1u] =
src64[src_row + x_words[src_x + local_x + 1u]];
dst64[dst_row + local_x + 2u] =
src64[src_row + x_words[src_x + local_x + 2u]];
dst64[dst_row + local_x + 3u] =
src64[src_row + x_words[src_x + local_x + 3u]];
dst64[dst_row + local_x + 4u] =
src64[src_row + x_words[src_x + local_x + 4u]];
dst64[dst_row + local_x + 5u] =
src64[src_row + x_words[src_x + local_x + 5u]];
dst64[dst_row + local_x + 6u] =
src64[src_row + x_words[src_x + local_x + 6u]];
dst64[dst_row + local_x + 7u] =
src64[src_row + x_words[src_x + local_x + 7u]];
}
}
continue;
}
for (uint32_t local_y = 0; local_y < block_height; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch_elements) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < block_width; local_x++) {
const uint64_t dst_index = dst_row + local_x;
const uint64_t src_index = src_row + x_words[src_x + local_x];
if (src_index < src_size_words && dst_index < size_words) {
dst64[dst_index] = src64[src_index];
}
}
}
}
}
ConvertTiledToLinearStandard64KBElements<uint64_t, 128u, 64u, 8u, false>(
dst, src, width_elements, height_elements, pitch_elements, size, src_size, src_x, src_y,
GetStandard64KB64Tables());
}
static void TileConvertLinearToTiledStandard64KB64Elements(
@@ -1822,82 +1605,9 @@ static void TileConvertTiledToLinearStandard64KB128Elements(
uint32_t pitch_elements, uint64_t size, uint64_t src_size, uint32_t src_x, uint32_t src_y) {
KYTY_PROFILER_FUNCTION();
EXIT_IF(dst == nullptr || src == nullptr);
EXIT_NOT_IMPLEMENTED(pitch_elements == 0);
const bool tail_block = (src_size != 0 && (src_x != 0 || src_y != 0 || size < src_size));
EXIT_NOT_IMPLEMENTED(width_elements > pitch_elements);
EXIT_NOT_IMPLEMENTED(tail_block &&
(src_x + width_elements > 64u || src_y + height_elements > 64u));
auto* dst128 = static_cast<Uint128*>(dst);
const auto* src128 = static_cast<const Uint128*>(src);
const auto& tables = GetStandard64KB128Tables();
const auto size_words = size >> 4u;
const auto src_size_words = (src_size != 0 ? src_size : size) >> 4u;
const auto blocks_per_row =
(tail_block ? 1u : static_cast<uint64_t>(AlignUp(pitch_elements, 64u) >> 6u));
const auto dst_words = static_cast<uint64_t>(pitch_elements) * height_elements;
const bool exact_surface = (!tail_block && (size & 15u) == 0 && size_words == dst_words);
const auto* x_words = tables.x_words.data();
const auto* y_words = tables.y_words.data();
if (!exact_surface) {
std::memset(dst128, 0, static_cast<size_t>(size));
}
for (uint32_t block_y = 0; block_y < height_elements; block_y += 64u) {
const uint32_t block_height = std::min(64u, height_elements - block_y);
for (uint32_t block_x = 0; block_x < width_elements; block_x += 64u) {
const uint32_t block_width = std::min(64u, width_elements - block_x);
const uint64_t block_base =
(tail_block
? 0u
: (((static_cast<uint64_t>(block_y) >> 6u) * blocks_per_row) + (block_x >> 6u))
<< 12u);
const bool full_block =
(!tail_block && block_width == 64u && block_height == 64u &&
block_base + 4096u <= src_size_words &&
(static_cast<uint64_t>(block_y + 63u) * pitch_elements) + block_x + 63u <
size_words);
if (full_block) {
for (uint32_t local_y = 0; local_y < 64u; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch_elements) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < 64u; local_x += 4u) {
dst128[dst_row + local_x + 0u] =
src128[src_row + x_words[src_x + local_x + 0u]];
dst128[dst_row + local_x + 1u] =
src128[src_row + x_words[src_x + local_x + 1u]];
dst128[dst_row + local_x + 2u] =
src128[src_row + x_words[src_x + local_x + 2u]];
dst128[dst_row + local_x + 3u] =
src128[src_row + x_words[src_x + local_x + 3u]];
}
}
continue;
}
for (uint32_t local_y = 0; local_y < block_height; local_y++) {
const uint64_t dst_row =
(static_cast<uint64_t>(block_y + local_y) * pitch_elements) + block_x;
const uint64_t src_row = block_base + y_words[src_y + local_y];
for (uint32_t local_x = 0; local_x < block_width; local_x++) {
const uint64_t dst_index = dst_row + local_x;
const uint64_t src_index = src_row + x_words[src_x + local_x];
if (src_index < src_size_words && dst_index < size_words) {
dst128[dst_index] = src128[src_index];
}
}
}
}
}
ConvertTiledToLinearStandard64KBElements<Uint128, 64u, 64u, 4u, false>(
dst, src, width_elements, height_elements, pitch_elements, size, src_size, src_x, src_y,
GetStandard64KB128Tables());
}
void TileConvertTiledToLinearStandard64KB(void* dst, const void* src, uint32_t format,