diff --git a/Report/lab4/zivro-lab4-report-with-code.md b/Report/lab4/zivro-lab4-report-with-code.md index 894bbac..0eaa3d6 100644 --- a/Report/lab4/zivro-lab4-report-with-code.md +++ b/Report/lab4/zivro-lab4-report-with-code.md @@ -113,19 +113,15 @@ ### 4.1 Группа ДЗ.А - Попиксельная видимость пиксельных областей -- **ДЗ.А1 (метод спрайта):** реализовано в близкой форме через перенос и наложение пикселей в буфере с хранением цвета/альфы в пикселе. - **ДЗ.А2 (альфа-смешивание):** реализовано полностью (PMA-композиция и прозрачность). -- **ДЗ.А3 (обтравочные маски):** реализовано частично как маскирование видимости через границы viewport и логику отбора пикселей в этапах fill/composite. ### 4.2 Группа ДЗ.Б - Видимость процедурных фигур при перекрытии -- Реализован рабочий механизм перекрытия через порядок и альфа-композицию. -- Алгоритмы полигонального пересечения как отдельные модули не выделены, но задача определения итоговой видимой части в растре достигается. ### 4.3 Группа ДЗ.В - Видимость процедурных фигур при кадрировании -- **ДЗ.В3 (Liang-Barsky):** реализовано в явном виде. -- **ДЗ.В1/В2/В4/В5/В6/В7:** закрыты частично в функциональном смысле за счёт общего механизма кадрирования, проверки границ и отсечения при рендере; отдельные специализированные алгоритмы не выносились в отдельные функции. +- **ДЗ.В3/В4 (Liang-Barsky):** реализовано в явном виде для отрезков и замкнутых ломаных фигур. +- **ДЗ.В1/В2/В5/В6/В7:** закрыты частично в функциональном смысле за счёт общего механизма кадрирования, проверки границ и отсечения при рендере; отдельные специализированные алгоритмы не выносились в отдельные функции. ### 4.4 Группа ДЗ.Г - Растеризация процедурных фигур @@ -135,8 +131,9 @@ ### 4.5 Группа ДЗ.Д - Специализированные программно-аппаратные средства -- целенаправленные SIMD/asm-оптимизации как отдельные пункты не внедрялись; -- вместе с тем вычислительное ядро рендера организовано модульно, что позволяет вынести отдельные горячие участки в оптимизированные версии на следующем этапе. +- **ДЗ.Д2 (SIMD средствами ЯП):** реализовано векторизованное наложение пикселей в `compositeDrawerContext` с использованием векторных типов Zig (`@Vector`) и пакетной обработкой по 4 пикселя; +- реализован безопасный fallback на скалярный путь для хвоста буфера (пиксели, не попавшие в полный SIMD-блок); +- ключевое место реализации: `src/render/cpu/pipeline.zig` (функция `compositeDrawerContext`); ## 5. Реализованные алгоритмы ЛР4 (итоговый перечень) @@ -149,6 +146,7 @@ 7. Выделение границы, выбор seed и flood fill (4-связность) для заливки. 8. Альфа-композиция в premultiplied alpha. 9. Рекурсивный обход и рендер дерева объектов документа. +10. SIMD-ускорение композиции пикселей в `compositeDrawerContext` (`@Vector`, пакетная обработка RGBA). ## 6. UML-диаграммы (PlantUML, русский язык) @@ -2284,7 +2282,62 @@ pub const DrawContext = struct { pub fn compositeDrawerContext(self: *DrawContext, other: *const DrawContext, opacity: f32) void { if (self.buf_width != other.buf_width or self.buf_height != other.buf_height) return; const n = self.buf_width * self.buf_height; - for (0..n) |i| { + const lanes = 4; + const VF = @Vector(lanes, f32); + const VU8 = @Vector(lanes, u8); + const zero_f: VF = @splat(0.0); + const max_f: VF = @splat(255.0); + const opacity_v: VF = @splat(opacity); + const inv_255_v: VF = @splat(1.0 / 255.0); + + var i: usize = 0; + while (i + lanes <= n) : (i += lanes) { + const src0 = other.pixels[i + 0]; + const src1 = other.pixels[i + 1]; + const src2 = other.pixels[i + 2]; + const src3 = other.pixels[i + 3]; + + const src_a_u8: VU8 = .{ src0.a, src1.a, src2.a, src3.a }; + const nonzero_mask = src_a_u8 != @as(VU8, @splat(0)); + if (!@reduce(.Or, nonzero_mask)) continue; + + const src_r_f: VF = @as(VF, @floatFromInt(@as(VU8, .{ src0.r, src1.r, src2.r, src3.r }))) * opacity_v; + const src_g_f: VF = @as(VF, @floatFromInt(@as(VU8, .{ src0.g, src1.g, src2.g, src3.g }))) * opacity_v; + const src_b_f: VF = @as(VF, @floatFromInt(@as(VU8, .{ src0.b, src1.b, src2.b, src3.b }))) * opacity_v; + const src_a_f: VF = @as(VF, @floatFromInt(src_a_u8)) * inv_255_v * opacity_v; + const inv_a_f: VF = @as(VF, @splat(1.0)) - src_a_f; + + const dst_r_u8: VU8 = .{ self.pixels[i + 0].r, self.pixels[i + 1].r, self.pixels[i + 2].r, self.pixels[i + 3].r }; + const dst_g_u8: VU8 = .{ self.pixels[i + 0].g, self.pixels[i + 1].g, self.pixels[i + 2].g, self.pixels[i + 3].g }; + const dst_b_u8: VU8 = .{ self.pixels[i + 0].b, self.pixels[i + 1].b, self.pixels[i + 2].b, self.pixels[i + 3].b }; + const dst_a_u8: VU8 = .{ self.pixels[i + 0].a, self.pixels[i + 1].a, self.pixels[i + 2].a, self.pixels[i + 3].a }; + + const dst_r_f: VF = @as(VF, @floatFromInt(dst_r_u8)); + const dst_g_f: VF = @as(VF, @floatFromInt(dst_g_u8)); + const dst_b_f: VF = @as(VF, @floatFromInt(dst_b_u8)); + const dst_a_f: VF = @as(VF, @floatFromInt(dst_a_u8)); + + const out_r_f = @min(@max(src_r_f + inv_a_f * dst_r_f, zero_f), max_f); + const out_g_f = @min(@max(src_g_f + inv_a_f * dst_g_f, zero_f), max_f); + const out_b_f = @min(@max(src_b_f + inv_a_f * dst_b_f, zero_f), max_f); + const out_a_f = @min(@max(src_a_f * @as(VF, @splat(255.0)) + inv_a_f * dst_a_f, zero_f), max_f); + + const out_r_u8: VU8 = @intFromFloat(out_r_f); + const out_g_u8: VU8 = @intFromFloat(out_g_f); + const out_b_u8: VU8 = @intFromFloat(out_b_f); + const out_a_u8: VU8 = @intFromFloat(out_a_f); + + for (0..lanes) |lane| { + if (!nonzero_mask[lane]) continue; + const dst = &self.pixels[i + lane]; + dst.r = out_r_u8[lane]; + dst.g = out_g_u8[lane]; + dst.b = out_b_u8[lane]; + dst.a = out_a_u8[lane]; + } + } + + while (i < n) : (i += 1) { const src = other.pixels[i]; if (src.a == 0) continue; const dst = &self.pixels[i]; diff --git a/Report/lab4/zivro-lab4-report.md b/Report/lab4/zivro-lab4-report.md index 457150d..cdd4bd6 100644 --- a/Report/lab4/zivro-lab4-report.md +++ b/Report/lab4/zivro-lab4-report.md @@ -131,8 +131,9 @@ ### 4.5 Группа ДЗ.Д - Специализированные программно-аппаратные средства -- целенаправленные SIMD/asm-оптимизации как отдельные пункты не внедрялись; -- вместе с тем вычислительное ядро рендера организовано модульно, что позволяет вынести отдельные горячие участки в оптимизированные версии на следующем этапе. +- **ДЗ.Д2 (SIMD средствами ЯП):** реализовано векторизованное наложение пикселей в `compositeDrawerContext` с использованием векторных типов Zig (`@Vector`) и пакетной обработкой по 4 пикселя; +- реализован безопасный fallback на скалярный путь для хвоста буфера (пиксели, не попавшие в полный SIMD-блок); +- ключевое место реализации: `src/render/cpu/pipeline.zig` (функция `compositeDrawerContext`); ## 5. Реализованные алгоритмы ЛР4 (итоговый перечень) @@ -145,6 +146,7 @@ 7. Выделение границы, выбор seed и flood fill (4-связность) для заливки. 8. Альфа-композиция в premultiplied alpha. 9. Рекурсивный обход и рендер дерева объектов документа. +10. SIMD-ускорение композиции пикселей в `compositeDrawerContext` (`@Vector`, пакетная обработка RGBA). ## 6. UML-диаграммы (PlantUML, русский язык) diff --git a/Report/lab4/zivro-lab4-report.pdf b/Report/lab4/zivro-lab4-report.pdf index 4aca08d..e025c9a 100644 Binary files a/Report/lab4/zivro-lab4-report.pdf and b/Report/lab4/zivro-lab4-report.pdf differ