diff --git a/implementations/Crafter.Graphics-Device.cpp b/implementations/Crafter.Graphics-Device.cpp index 644fb67..5845570 100644 --- a/implementations/Crafter.Graphics-Device.cpp +++ b/implementations/Crafter.Graphics-Device.cpp @@ -475,7 +475,7 @@ void Device::Initialize() { VkApplicationInfo app{VK_STRUCTURE_TYPE_APPLICATION_INFO}; app.pApplicationName = ""; app.pEngineName = "Crafter.Graphics"; - app.apiVersion = VK_MAKE_VERSION(1, 4, 0); + app.apiVersion = VK_MAKE_VERSION(1, 3, 0); VkInstanceCreateInfo instanceCreateInfo = {}; instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; diff --git a/implementations/Crafter.Graphics-Transform2D.cpp b/implementations/Crafter.Graphics-Transform2D.cpp index 6381950..ff7d4b0 100644 --- a/implementations/Crafter.Graphics-Transform2D.cpp +++ b/implementations/Crafter.Graphics-Transform2D.cpp @@ -28,6 +28,6 @@ import std; using namespace Crafter; -Anchor2D::Anchor2D(float x, float y, float width, float height, float offsetX, float offsetY, std::int32_t z, bool maintainAspectRatio): x(x), y(y), width(width), height(height), offsetX(offsetX), offsetY(offsetY), z(z), maintainAspectRatio(maintainAspectRatio) { +Anchor2D::Anchor2D(float x, float y, float width, float height, float offsetX, float offsetY, std::uint8_t z, bool maintainAspectRatio): x(x), y(y), width(width), height(height), offsetX(offsetX), offsetY(offsetY), z(z), maintainAspectRatio(maintainAspectRatio) { } \ No newline at end of file diff --git a/interfaces/Crafter.Graphics-RenderingElement2D.cppm b/interfaces/Crafter.Graphics-RenderingElement2D.cppm index 1dc448d..eb3ce7c 100644 --- a/interfaces/Crafter.Graphics-RenderingElement2D.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement2D.cppm @@ -29,31 +29,31 @@ import :Types; import :Window; export namespace Crafter { - template requires ((!Rotating || Scaling) && (!Owning || Scaling)) - struct RenderingElement2D : RenderingElement2DBase, ScalingBase, RotatingBase { + template requires ((!Rotating || Scaling) && (!Owning || Scaling)) + struct RenderingElement2D : RenderingElement2DBase, ScalingBase, RotatingBase { RenderingElement2D() = default; - RenderingElement2D(Anchor2D anchor, OpaqueType opaque) : RenderingElement2DBase(anchor, opaque) { + RenderingElement2D(Anchor2D anchor, OpaqueType opaque) : RenderingElement2DBase(anchor, opaque) { } - RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t rotation) requires(Rotating) : RenderingElement2DBase(anchor, opaque), RotatingBase(rotation) { + RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t rotation) requires(Rotating) : RenderingElement2DBase(anchor, opaque), RotatingBase(rotation) { } - RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector* scalingBuffer) requires(Scaling && !Owning) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight, scalingBuffer) { + RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector* scalingBuffer) requires(Scaling && !Owning) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight, scalingBuffer) { } - RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector* scalingBuffer, std::uint32_t rotation) requires(Scaling && !Owning && Rotating) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight, scalingBuffer), RotatingBase(rotation) { + RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector* scalingBuffer, std::uint32_t rotation) requires(Scaling && !Owning && Rotating) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight, scalingBuffer), RotatingBase(rotation) { } - RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight) requires(Owning) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight) { + RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight) requires(Owning) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight) { } - RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, std::uint32_t rotation) requires(Owning && Rotating) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight) , RotatingBase(rotation) { + RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, std::uint32_t rotation) requires(Owning && Rotating) : RenderingElement2DBase(anchor, opaque), ScalingBase(bufferWidth, bufferHeight) , RotatingBase(rotation) { } - RenderingElement2D(Anchor2D anchor, TextureAsset>& texture) requires(!Owning && Scaling) : RenderingElement2DBase(anchor, texture.opaque), ScalingBase(texture.pixels.data(), texture.sizeX, texture.sizeY) { + RenderingElement2D(Anchor2D anchor, TextureAsset>& texture) requires(!Owning && Scaling) : RenderingElement2DBase(anchor, texture.opaque), ScalingBase(texture.pixels.data(), texture.sizeX, texture.sizeY) { } - RenderingElement2D(Anchor2D anchor, TextureAsset>& texture, std::uint32_t rotation) requires(!Owning && Scaling && Rotating) : RenderingElement2DBase(anchor, texture.opaque), ScalingBase(texture.pixels.data(), texture.sizeX, texture.sizeY), RotatingBase(rotation) { + RenderingElement2D(Anchor2D anchor, TextureAsset>& texture, std::uint32_t rotation) requires(!Owning && Scaling && Rotating) : RenderingElement2DBase(anchor, texture.opaque), ScalingBase(texture.pixels.data(), texture.sizeX, texture.sizeY), RotatingBase(rotation) { } diff --git a/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm b/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm index 7b78164..d86fab1 100644 --- a/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm +++ b/interfaces/Crafter.Graphics-RenderingElement2DBase.cppm @@ -94,11 +94,11 @@ export namespace Crafter { EmptyRotatingBase >; - template + template struct RenderingElement2DBase : Transform2D { ScaleData2D oldScale[Frames]; bool redraw[Frames]; - std::vector> buffer; + std::vector> buffer; OpaqueType opaque; RenderingElement2DBase(Anchor2D anchor) : Transform2D(anchor) { for(std::uint8_t i = 0; i < Frames; i++) { diff --git a/interfaces/Crafter.Graphics-Rendertarget.cppm b/interfaces/Crafter.Graphics-Rendertarget.cppm index 5084c37..77dd2e9 100644 --- a/interfaces/Crafter.Graphics-Rendertarget.cppm +++ b/interfaces/Crafter.Graphics-Rendertarget.cppm @@ -46,11 +46,11 @@ export namespace Crafter { struct Rendertarget : RendertargetBase { Vector* buffer[Frames]; Rendertarget() = default; - Rendertarget(std::int16_t sizeX, std::int16_t sizeY) : RendertargetBase(sizeX, sizeY) { + Rendertarget(std::uint16_t sizeX, std::uint16_t sizeY) : RendertargetBase(sizeX, sizeY) { } void RenderElement(Transform2D* elementTransform, std::uint8_t frame, std::vector&& dirtyRects) { - RenderingElement2DBase* element = dynamic_cast*>(elementTransform); + RenderingElement2DBase* element = dynamic_cast*>(elementTransform); if(element) { #ifdef CRAFTER_TIMING auto start = std::chrono::high_resolution_clock::now(); @@ -63,10 +63,10 @@ export namespace Crafter { for(ClipRect dirty : dirtyRects) { dirty.left = std::max(element->scaled.position.x, dirty.left); dirty.top = std::max(element->scaled.position.y, dirty.top); - dirty.right = std::min(element->scaled.position.x+element->scaled.size.x, dirty.right); - dirty.bottom = std::min(element->scaled.position.y+element->scaled.size.y, dirty.bottom); + dirty.right = std::min(std::uint16_t(element->scaled.position.x+element->scaled.size.x), dirty.right); + dirty.bottom = std::min(std::uint16_t(element->scaled.position.y+element->scaled.size.y), dirty.bottom); - const Vector* src_buffer = element->buffer.data(); + const Vector* src_buffer = element->buffer.data(); std::int32_t src_width = element->scaled.size.x; std::int32_t src_height = element->scaled.size.y; @@ -83,65 +83,46 @@ export namespace Crafter { if constexpr(std::same_as) { for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) { std::uint16_t src_y = y - element->scaled.position.y; - std::uint16_t rowSize = dirty.right - dirty.left; - constexpr std::uint8_t elementsPerVector = VectorF16L<1, 1, 1>::MaxSize/VectorF16L<1, 1, 1>::MaxElement; - while(rowSize > 0) { - if(rowSize < elementsPerVector) { - for(; rowSize > 0; rowSize--) { - std::uint16_t src_x = rowSize - element->scaled.position.x; - Vector src = src_buffer[src_y * src_width + src_x]; - Vector dst = buffer[frame][y * this->sizeX + rowSize]; + std::uint32_t pixel_width = dirty.right - dirty.left; + constexpr std::uint32_t simd_width = VectorF16<1, 1>::MaxElement / 4; + std::uint32_t rows = pixel_width / simd_width; - _Float16 outA = src.a + dst.a * (1.0f - src.a); - this->buffer[frame][y * this->sizeX + rowSize] = Vector( - static_cast((src.r + dst.r * (1.0f - src.a)) / outA), - static_cast((src.g + dst.g * (1.0f - src.a)) / outA), - static_cast((src.b + dst.b * (1.0f - src.a)) / outA), - static_cast(outA * 255) - ); - } - break; - } else { - std::uint16_t src_x = rowSize - element->scaled.position.x; - using VectorType = VectorF16L<4, VectorF16L<1, 1, 1>::MaxElement / 4, VectorF16L<1, 1, 1>::MaxSize/((VectorF16L<1, 1, 1>::MaxElement / 4)*4)>; - VectorType src(src_buffer[src_y * src_width + src_x].v); - VectorType dst(buffer[frame][y * this->sizeX + rowSize].v); + for (std::uint32_t x = 0; x < rows; x++) { + std::uint16_t px = dirty.left + x * simd_width; + std::uint16_t src_x = px - element->scaled.position.x; + std::uint16_t dst_x = px; - VectorType srcA = src.ShufflePacked<3,3,3,3>(); - VectorType dstA = dst.ShufflePacked<3,3,3,3>(); - - VectorType srcANeg = -srcA; - - VectorType outA = VectorType::MulitplyAdd(dstA, srcANeg, srcA); - - VectorType result = src + dst * srcANeg / outA; - result = VectorType::BlendPacked<0,0,0,1>(dst, outA); - result.Store(buffer[frame][y * this->sizeX + rowSize].v); - - rowSize -= elementsPerVector; - } + VectorF16<4, simd_width> src(&src_buffer[src_y * src_width + src_x].v[0]); + VectorF16<4, simd_width> dst(&buffer[frame][y * this->sizeX + dst_x].v[0]); + VectorF16<4, simd_width> oneMinusSrcA = VectorF16<4, simd_width>(1) - src.Shuffle<{{3, 3, 3, 3}}>(); + VectorF16<4, simd_width> result = VectorF16<4, simd_width>::MulitplyAdd(dst, oneMinusSrcA, src); + result.Store(buffer[frame][y * this->sizeX + dst_x]); } - } - } else { - for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) { - std::uint16_t src_y = y - element->scaled.position.y; - for (std::uint16_t x = dirty.left; x < dirty.right; x++) { - std::uint16_t src_x = x - element->scaled.position.x; - Vector src = src_buffer[src_y * src_width + src_x]; - Vector dst = buffer[frame][y * this->sizeX + x]; - - float srcA = src.a / 255.0f; - float dstA = dst.a / 255.0f; - float outA = srcA + dstA * (1.0f - srcA); - this->buffer[frame][y * this->sizeX + x] = Vector( - static_cast((src.r + dst.r * (1.0f - srcA)) / outA), - static_cast((src.g + dst.g * (1.0f - srcA)) / outA), - static_cast((src.b + dst.b * (1.0f - srcA)) / outA), - static_cast(outA * 255) + std::uint32_t remainder = pixel_width - (rows * simd_width); + std::uint16_t remainder_start = dirty.left + rows * simd_width; + + for (std::uint8_t x = 0; x < remainder; x++) { + std::uint16_t px = remainder_start + x; + std::uint16_t src_x = px - element->scaled.position.x; + + Vector src = src_buffer[src_y * src_width + src_x]; + Vector dst = buffer[frame][y * this->sizeX + px]; + _Float16 oneMinusSrcA = (_Float16)1.0f - src[3]; + + buffer[frame][y * this->sizeX + px] = Vector( + src.r + dst.r * oneMinusSrcA, + src.g + dst.g * oneMinusSrcA, + src.b + dst.b * oneMinusSrcA, + src.a + dst.a * oneMinusSrcA ); } } + } else { + for (std::int32_t y = dirty.top; y < dirty.bottom; y++) { + std::int32_t src_y = y - element->scaled.position.y; + std::memcpy(&this->buffer[frame][y * this->sizeX], &src_buffer[src_y * src_width], dirty.right-dirty.left*sizeof(Vector)); + } } break; } @@ -158,15 +139,15 @@ export namespace Crafter { } void AddOldRects(Transform2D* elementTransform, std::uint8_t frame, std::vector& clipRects) { - RenderingElement2DBase* element = dynamic_cast*>(elementTransform); + RenderingElement2DBase* element = dynamic_cast*>(elementTransform); if(element) { if(element->scaled.position.x != element->oldScale[frame].position.x || element->scaled.position.y != element->oldScale[frame].position.y || element->scaled.size.x != element->oldScale[frame].size.x || element->scaled.size.y != element->oldScale[frame].size.y || element->redraw[frame]) { - clipRects.emplace_back(std::max(element->scaled.position.x, std::int32_t(0)), std::min(element->scaled.position.x + element->scaled.size.x, this->sizeX), std::max(element->scaled.position.y, std::int32_t(0)), std::min(element->scaled.position.y + element->scaled.size.y, this->sizeY)); - clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::int32_t(0)), std::min(element->oldScale[frame].position.x + element->oldScale[frame].size.x, this->sizeX), std::max(element->oldScale[frame].position.y, std::int32_t(0)), std::min(element->oldScale[frame].position.y + element->oldScale[frame].size.y, this->sizeY)); + clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY)); + clipRects.emplace_back(std::max(element->oldScale[frame].position.x, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.x + element->oldScale[frame].size.x), this->sizeX), std::max(element->oldScale[frame].position.y, std::uint16_t(0)), std::min(std::uint16_t(element->oldScale[frame].position.y + element->oldScale[frame].size.y), this->sizeY)); element->oldScale[frame] = element->scaled; element->redraw[frame] = false; } else if(element->redraw[frame]) { - clipRects.emplace_back(std::max(element->scaled.position.x, std::int32_t(0)), std::min(element->scaled.position.x + element->scaled.size.x, this->sizeX), std::max(element->scaled.position.y, std::int32_t(0)), std::min(element->scaled.position.y + element->scaled.size.y, this->sizeY)); + clipRects.emplace_back(std::max(element->scaled.position.x, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.x + element->scaled.size.x), this->sizeX), std::max(element->scaled.position.y, std::uint16_t(0)), std::min(std::uint16_t(element->scaled.position.y + element->scaled.size.y), this->sizeY)); element->oldScale[frame] = element->scaled; element->redraw[frame] = false; }