vector renderring
This commit is contained in:
commit
c895c266fb
5 changed files with 53 additions and 72 deletions
|
|
@ -475,7 +475,7 @@ void Device::Initialize() {
|
||||||
VkApplicationInfo app{VK_STRUCTURE_TYPE_APPLICATION_INFO};
|
VkApplicationInfo app{VK_STRUCTURE_TYPE_APPLICATION_INFO};
|
||||||
app.pApplicationName = "";
|
app.pApplicationName = "";
|
||||||
app.pEngineName = "Crafter.Graphics";
|
app.pEngineName = "Crafter.Graphics";
|
||||||
app.apiVersion = VK_MAKE_VERSION(1, 4, 0);
|
app.apiVersion = VK_MAKE_VERSION(1, 3, 0);
|
||||||
|
|
||||||
VkInstanceCreateInfo instanceCreateInfo = {};
|
VkInstanceCreateInfo instanceCreateInfo = {};
|
||||||
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,6 @@ import std;
|
||||||
using namespace Crafter;
|
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) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -29,31 +29,31 @@ import :Types;
|
||||||
import :Window;
|
import :Window;
|
||||||
|
|
||||||
export namespace Crafter {
|
export namespace Crafter {
|
||||||
template<bool Scaling, bool Owning, bool Rotating, std::uint8_t Alignment = 0, std::uint8_t Frames = 1> requires ((!Rotating || Scaling) && (!Owning || Scaling))
|
template<typename T, bool Scaling, bool Owning, bool Rotating, std::uint8_t Alignment = 0, std::uint8_t Frames = 1> requires ((!Rotating || Scaling) && (!Owning || Scaling))
|
||||||
struct RenderingElement2D : RenderingElement2DBase<Frames>, ScalingBase<Scaling, Owning, Alignment>, RotatingBase<Rotating> {
|
struct RenderingElement2D : RenderingElement2DBase<T, Frames>, ScalingBase<Scaling, Owning, Alignment>, RotatingBase<Rotating> {
|
||||||
RenderingElement2D() = default;
|
RenderingElement2D() = default;
|
||||||
RenderingElement2D(Anchor2D anchor, OpaqueType opaque) : RenderingElement2DBase<Frames>(anchor, opaque) {
|
RenderingElement2D(Anchor2D anchor, OpaqueType opaque) : RenderingElement2DBase<T, Frames>(anchor, opaque) {
|
||||||
|
|
||||||
}
|
}
|
||||||
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t rotation) requires(Rotating) : RenderingElement2DBase<Frames>(anchor, opaque), RotatingBase<Rotating>(rotation) {
|
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t rotation) requires(Rotating) : RenderingElement2DBase<T, Frames>(anchor, opaque), RotatingBase<Rotating>(rotation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector<std::uint8_t, 4, Alignment>* scalingBuffer) requires(Scaling && !Owning) : RenderingElement2DBase<Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight, scalingBuffer) {
|
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector<std::uint8_t, 4, Alignment>* scalingBuffer) requires(Scaling && !Owning) : RenderingElement2DBase<T, Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight, scalingBuffer) {
|
||||||
|
|
||||||
}
|
}
|
||||||
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector<std::uint8_t, 4, Alignment>* scalingBuffer, std::uint32_t rotation) requires(Scaling && !Owning && Rotating) : RenderingElement2DBase<Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight, scalingBuffer), RotatingBase<Rotating>(rotation) {
|
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, Vector<std::uint8_t, 4, Alignment>* scalingBuffer, std::uint32_t rotation) requires(Scaling && !Owning && Rotating) : RenderingElement2DBase<T, Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight, scalingBuffer), RotatingBase<Rotating>(rotation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight) requires(Owning) : RenderingElement2DBase<Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight) {
|
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight) requires(Owning) : RenderingElement2DBase<T, Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight) {
|
||||||
|
|
||||||
}
|
}
|
||||||
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, std::uint32_t rotation) requires(Owning && Rotating) : RenderingElement2DBase<Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight) , RotatingBase<Rotating>(rotation) {
|
RenderingElement2D(Anchor2D anchor, OpaqueType opaque, std::uint32_t bufferWidth, std::uint32_t bufferHeight, std::uint32_t rotation) requires(Owning && Rotating) : RenderingElement2DBase<T, Frames>(anchor, opaque), ScalingBase<Scaling, Owning, Alignment>(bufferWidth, bufferHeight) , RotatingBase<Rotating>(rotation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
RenderingElement2D(Anchor2D anchor, TextureAsset<Vector<std::uint8_t, 4, Alignment>>& texture) requires(!Owning && Scaling) : RenderingElement2DBase<Frames>(anchor, texture.opaque), ScalingBase<Scaling, Owning, Alignment>(texture.pixels.data(), texture.sizeX, texture.sizeY) {
|
RenderingElement2D(Anchor2D anchor, TextureAsset<Vector<std::uint8_t, 4, Alignment>>& texture) requires(!Owning && Scaling) : RenderingElement2DBase<T, Frames>(anchor, texture.opaque), ScalingBase<Scaling, Owning, Alignment>(texture.pixels.data(), texture.sizeX, texture.sizeY) {
|
||||||
|
|
||||||
}
|
}
|
||||||
RenderingElement2D(Anchor2D anchor, TextureAsset<Vector<std::uint8_t, 4, Alignment>>& texture, std::uint32_t rotation) requires(!Owning && Scaling && Rotating) : RenderingElement2DBase<Frames>(anchor, texture.opaque), ScalingBase<Scaling, Owning, Alignment>(texture.pixels.data(), texture.sizeX, texture.sizeY), RotatingBase<Rotating>(rotation) {
|
RenderingElement2D(Anchor2D anchor, TextureAsset<Vector<std::uint8_t, 4, Alignment>>& texture, std::uint32_t rotation) requires(!Owning && Scaling && Rotating) : RenderingElement2DBase<T, Frames>(anchor, texture.opaque), ScalingBase<Scaling, Owning, Alignment>(texture.pixels.data(), texture.sizeX, texture.sizeY), RotatingBase<Rotating>(rotation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -94,11 +94,11 @@ export namespace Crafter {
|
||||||
EmptyRotatingBase
|
EmptyRotatingBase
|
||||||
>;
|
>;
|
||||||
|
|
||||||
template<std::uint8_t Frames = 1>
|
template<typename T, std::uint8_t Frames = 1>
|
||||||
struct RenderingElement2DBase : Transform2D {
|
struct RenderingElement2DBase : Transform2D {
|
||||||
ScaleData2D oldScale[Frames];
|
ScaleData2D oldScale[Frames];
|
||||||
bool redraw[Frames];
|
bool redraw[Frames];
|
||||||
std::vector<Vector<std::uint8_t, 4>> buffer;
|
std::vector<Vector<T, 4, 4>> buffer;
|
||||||
OpaqueType opaque;
|
OpaqueType opaque;
|
||||||
RenderingElement2DBase(Anchor2D anchor) : Transform2D(anchor) {
|
RenderingElement2DBase(Anchor2D anchor) : Transform2D(anchor) {
|
||||||
for(std::uint8_t i = 0; i < Frames; i++) {
|
for(std::uint8_t i = 0; i < Frames; i++) {
|
||||||
|
|
|
||||||
|
|
@ -46,11 +46,11 @@ export namespace Crafter {
|
||||||
struct Rendertarget : RendertargetBase<Frames> {
|
struct Rendertarget : RendertargetBase<Frames> {
|
||||||
Vector<T, Channels, Alignment>* buffer[Frames];
|
Vector<T, Channels, Alignment>* buffer[Frames];
|
||||||
Rendertarget() = default;
|
Rendertarget() = default;
|
||||||
Rendertarget(std::int16_t sizeX, std::int16_t sizeY) : RendertargetBase<Frames>(sizeX, sizeY) {
|
Rendertarget(std::uint16_t sizeX, std::uint16_t sizeY) : RendertargetBase<Frames>(sizeX, sizeY) {
|
||||||
|
|
||||||
}
|
}
|
||||||
void RenderElement(Transform2D* elementTransform, std::uint8_t frame, std::vector<ClipRect>&& dirtyRects) {
|
void RenderElement(Transform2D* elementTransform, std::uint8_t frame, std::vector<ClipRect>&& dirtyRects) {
|
||||||
RenderingElement2DBase<Frames>* element = dynamic_cast<RenderingElement2DBase<Frames>*>(elementTransform);
|
RenderingElement2DBase<T, Frames>* element = dynamic_cast<RenderingElement2DBase<T, Frames>*>(elementTransform);
|
||||||
if(element) {
|
if(element) {
|
||||||
#ifdef CRAFTER_TIMING
|
#ifdef CRAFTER_TIMING
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
|
@ -63,10 +63,10 @@ export namespace Crafter {
|
||||||
for(ClipRect dirty : dirtyRects) {
|
for(ClipRect dirty : dirtyRects) {
|
||||||
dirty.left = std::max(element->scaled.position.x, dirty.left);
|
dirty.left = std::max(element->scaled.position.x, dirty.left);
|
||||||
dirty.top = std::max(element->scaled.position.y, dirty.top);
|
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.right = std::min(std::uint16_t(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.bottom = std::min(std::uint16_t(element->scaled.position.y+element->scaled.size.y), dirty.bottom);
|
||||||
|
|
||||||
const Vector<std::uint8_t, 4>* src_buffer = element->buffer.data();
|
const Vector<T, 4, 4>* src_buffer = element->buffer.data();
|
||||||
std::int32_t src_width = element->scaled.size.x;
|
std::int32_t src_width = element->scaled.size.x;
|
||||||
std::int32_t src_height = element->scaled.size.y;
|
std::int32_t src_height = element->scaled.size.y;
|
||||||
|
|
||||||
|
|
@ -83,64 +83,45 @@ export namespace Crafter {
|
||||||
if constexpr(std::same_as<T, _Float16>) {
|
if constexpr(std::same_as<T, _Float16>) {
|
||||||
for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) {
|
for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) {
|
||||||
std::uint16_t src_y = y - element->scaled.position.y;
|
std::uint16_t src_y = y - element->scaled.position.y;
|
||||||
std::uint16_t rowSize = dirty.right - dirty.left;
|
std::uint32_t pixel_width = dirty.right - dirty.left;
|
||||||
constexpr std::uint8_t elementsPerVector = VectorF16L<1, 1, 1>::MaxSize/VectorF16L<1, 1, 1>::MaxElement;
|
constexpr std::uint32_t simd_width = VectorF16<1, 1>::MaxElement / 4;
|
||||||
while(rowSize > 0) {
|
std::uint32_t rows = pixel_width / simd_width;
|
||||||
if(rowSize < elementsPerVector) {
|
|
||||||
for(; rowSize > 0; rowSize--) {
|
|
||||||
std::uint16_t src_x = rowSize - element->scaled.position.x;
|
|
||||||
Vector<T, Channels, Alignment> src = src_buffer[src_y * src_width + src_x];
|
|
||||||
Vector<T, Channels, Alignment> dst = buffer[frame][y * this->sizeX + rowSize];
|
|
||||||
|
|
||||||
_Float16 outA = src.a + dst.a * (1.0f - src.a);
|
for (std::uint32_t x = 0; x < rows; x++) {
|
||||||
this->buffer[frame][y * this->sizeX + rowSize] = Vector<T, Channels, Alignment>(
|
std::uint16_t px = dirty.left + x * simd_width;
|
||||||
static_cast<T>((src.r + dst.r * (1.0f - src.a)) / outA),
|
std::uint16_t src_x = px - element->scaled.position.x;
|
||||||
static_cast<T>((src.g + dst.g * (1.0f - src.a)) / outA),
|
std::uint16_t dst_x = px;
|
||||||
static_cast<T>((src.b + dst.b * (1.0f - src.a)) / outA),
|
|
||||||
static_cast<T>(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);
|
|
||||||
|
|
||||||
VectorType srcA = src.ShufflePacked<3,3,3,3>();
|
VectorF16<4, simd_width> src(&src_buffer[src_y * src_width + src_x].v[0]);
|
||||||
VectorType dstA = dst.ShufflePacked<3,3,3,3>();
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
VectorType srcANeg = -srcA;
|
std::uint32_t remainder = pixel_width - (rows * simd_width);
|
||||||
|
std::uint16_t remainder_start = dirty.left + rows * simd_width;
|
||||||
|
|
||||||
VectorType outA = VectorType::MulitplyAdd(dstA, srcANeg, srcA);
|
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;
|
||||||
|
|
||||||
VectorType result = src + dst * srcANeg / outA;
|
Vector<T, Channels, Alignment> src = src_buffer[src_y * src_width + src_x];
|
||||||
result = VectorType::BlendPacked<0,0,0,1>(dst, outA);
|
Vector<T, Channels, Alignment> dst = buffer[frame][y * this->sizeX + px];
|
||||||
result.Store(buffer[frame][y * this->sizeX + rowSize].v);
|
_Float16 oneMinusSrcA = (_Float16)1.0f - src[3];
|
||||||
|
|
||||||
rowSize -= elementsPerVector;
|
buffer[frame][y * this->sizeX + px] = Vector<T, Channels, Alignment>(
|
||||||
}
|
src.r + dst.r * oneMinusSrcA,
|
||||||
|
src.g + dst.g * oneMinusSrcA,
|
||||||
|
src.b + dst.b * oneMinusSrcA,
|
||||||
|
src.a + dst.a * oneMinusSrcA
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) {
|
for (std::int32_t y = dirty.top; y < dirty.bottom; y++) {
|
||||||
std::uint16_t src_y = y - element->scaled.position.y;
|
std::int32_t src_y = y - element->scaled.position.y;
|
||||||
for (std::uint16_t x = dirty.left; x < dirty.right; x++) {
|
std::memcpy(&this->buffer[frame][y * this->sizeX], &src_buffer[src_y * src_width], dirty.right-dirty.left*sizeof(Vector<T, Channels, Alignment>));
|
||||||
std::uint16_t src_x = x - element->scaled.position.x;
|
|
||||||
Vector<T, Channels, Alignment> src = src_buffer[src_y * src_width + src_x];
|
|
||||||
Vector<T, Channels, Alignment> 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<T, Channels, Alignment>(
|
|
||||||
static_cast<T>((src.r + dst.r * (1.0f - srcA)) / outA),
|
|
||||||
static_cast<T>((src.g + dst.g * (1.0f - srcA)) / outA),
|
|
||||||
static_cast<T>((src.b + dst.b * (1.0f - srcA)) / outA),
|
|
||||||
static_cast<T>(outA * 255)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -158,15 +139,15 @@ export namespace Crafter {
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddOldRects(Transform2D* elementTransform, std::uint8_t frame, std::vector<ClipRect>& clipRects) {
|
void AddOldRects(Transform2D* elementTransform, std::uint8_t frame, std::vector<ClipRect>& clipRects) {
|
||||||
RenderingElement2DBase<Frames>* element = dynamic_cast<RenderingElement2DBase<Frames>*>(elementTransform);
|
RenderingElement2DBase<T, Frames>* element = dynamic_cast<RenderingElement2DBase<T, Frames>*>(elementTransform);
|
||||||
if(element) {
|
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]) {
|
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->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::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->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->oldScale[frame] = element->scaled;
|
||||||
element->redraw[frame] = false;
|
element->redraw[frame] = false;
|
||||||
} else if(element->redraw[frame]) {
|
} 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->oldScale[frame] = element->scaled;
|
||||||
element->redraw[frame] = false;
|
element->redraw[frame] = false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue