F16 rendering
This commit is contained in:
parent
c895c266fb
commit
477b7dd087
5 changed files with 120 additions and 79 deletions
|
|
@ -593,8 +593,14 @@ void Device::Initialize() {
|
||||||
queueCreateInfo.queueCount = 1;
|
queueCreateInfo.queueCount = 1;
|
||||||
queueCreateInfo.pQueuePriorities = &priority;
|
queueCreateInfo.pQueuePriorities = &priority;
|
||||||
|
|
||||||
|
VkPhysicalDevice16BitStorageFeatures bit16 {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES,
|
||||||
|
.storageBuffer16BitAccess = VK_TRUE,
|
||||||
|
};
|
||||||
|
|
||||||
VkPhysicalDeviceVulkan12Features features12 {
|
VkPhysicalDeviceVulkan12Features features12 {
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
|
||||||
|
.pNext = &bit16,
|
||||||
.runtimeDescriptorArray = VK_TRUE,
|
.runtimeDescriptorArray = VK_TRUE,
|
||||||
.bufferDeviceAddress = VK_TRUE
|
.bufferDeviceAddress = VK_TRUE
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -737,16 +737,7 @@ void Window::Render() {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
vkCmdBindPipeline(drawCmdBuffers[currentBuffer], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rtPipeline);
|
vkCmdBindPipeline(drawCmdBuffers[currentBuffer], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rtPipeline);
|
||||||
VkBindDescriptorSetsInfo bindDescriptorSetsInfo{
|
vkCmdBindDescriptorSets(drawCmdBuffers[currentBuffer], VK_PIPELINE_BIND_POINT_RAY_TRACING_KHR, rtPipelineLayout, 0, static_cast<std::uint32_t>(descriptorsRt.size()), descriptorsRt.data(), 0, nullptr);
|
||||||
.sType = VK_STRUCTURE_TYPE_BIND_DESCRIPTOR_SETS_INFO,
|
|
||||||
.stageFlags = VK_SHADER_STAGE_ALL,
|
|
||||||
.layout = rtPipelineLayout,
|
|
||||||
.firstSet = 0,
|
|
||||||
.descriptorSetCount = static_cast<std::uint32_t>(descriptorsRt.size()),
|
|
||||||
.pDescriptorSets = descriptorsRt.data()
|
|
||||||
};
|
|
||||||
|
|
||||||
vkCmdBindDescriptorSets2(drawCmdBuffers[currentBuffer], &bindDescriptorSetsInfo);
|
|
||||||
Device::vkCmdTraceRaysKHR(drawCmdBuffers[currentBuffer], &raygenRegion, &missRegion, &hitRegion, &callableRegion, width, height, 1);
|
Device::vkCmdTraceRaysKHR(drawCmdBuffers[currentBuffer], &raygenRegion, &missRegion, &hitRegion, &callableRegion, width, height, 1);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import :Window;
|
||||||
|
|
||||||
export namespace Crafter {
|
export namespace Crafter {
|
||||||
template<typename T, 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<T, Frames>, ScalingBase<Scaling, Owning, Alignment>, RotatingBase<Rotating> {
|
struct RenderingElement2D : RenderingElement2DBase<T, Frames>, ScalingBase<T, Scaling, Owning, Alignment>, RotatingBase<Rotating> {
|
||||||
RenderingElement2D() = default;
|
RenderingElement2D() = default;
|
||||||
RenderingElement2D(Anchor2D anchor, OpaqueType opaque) : RenderingElement2DBase<T, Frames>(anchor, opaque) {
|
RenderingElement2D(Anchor2D anchor, OpaqueType opaque) : RenderingElement2DBase<T, Frames>(anchor, opaque) {
|
||||||
|
|
||||||
|
|
@ -38,22 +38,22 @@ export namespace Crafter {
|
||||||
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 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<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<T, 4, Alignment>* scalingBuffer) requires(Scaling && !Owning) : RenderingElement2DBase<T, Frames>(anchor, opaque), ScalingBase<T, 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<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, Vector<T, 4, Alignment>* scalingBuffer, std::uint32_t rotation) requires(Scaling && !Owning && Rotating) : RenderingElement2DBase<T, Frames>(anchor, opaque), ScalingBase<T, 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<T, 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<T, 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<T, 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<T, Scaling, Owning, Alignment>(bufferWidth, bufferHeight) , RotatingBase<Rotating>(rotation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
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<T, 4, Alignment>>& texture) requires(!Owning && Scaling) : RenderingElement2DBase<T, Frames>(anchor, texture.opaque), ScalingBase<T, 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<T, Frames>(anchor, texture.opaque), ScalingBase<Scaling, Owning, Alignment>(texture.pixels.data(), texture.sizeX, texture.sizeY), RotatingBase<Rotating>(rotation) {
|
RenderingElement2D(Anchor2D anchor, TextureAsset<Vector<T, 4, Alignment>>& texture, std::uint32_t rotation) requires(!Owning && Scaling && Rotating) : RenderingElement2DBase<T, Frames>(anchor, texture.opaque), ScalingBase<T, Scaling, Owning, Alignment>(texture.pixels.data(), texture.sizeX, texture.sizeY), RotatingBase<Rotating>(rotation) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -62,10 +62,10 @@ export namespace Crafter {
|
||||||
|
|
||||||
void ScaleNearestNeighbor() requires(Scaling) {
|
void ScaleNearestNeighbor() requires(Scaling) {
|
||||||
for (std::uint32_t y = 0; y < this->scaled.size.y; y++) {
|
for (std::uint32_t y = 0; y < this->scaled.size.y; y++) {
|
||||||
std::uint32_t srcY = y * ScalingBase<true, Owning, Alignment>::bufferHeight / this->scaled.size.y;
|
std::uint32_t srcY = y * ScalingBase<T, true, Owning, Alignment>::bufferHeight / this->scaled.size.y;
|
||||||
for (std::uint32_t x = 0; x < this->scaled.size.x; x++) {
|
for (std::uint32_t x = 0; x < this->scaled.size.x; x++) {
|
||||||
std::uint32_t srcX = x * ScalingBase<true, Owning, Alignment>::bufferWidth / this->scaled.size.x;
|
std::uint32_t srcX = x * ScalingBase<T, true, Owning, Alignment>::bufferWidth / this->scaled.size.x;
|
||||||
this->buffer[y * this->scaled.size.x + x] = ScalingBase<true, Owning, Alignment>::scalingBuffer[srcY * ScalingBase<true, Owning, Alignment>::bufferWidth + srcX];
|
this->buffer[y * this->scaled.size.x + x] = ScalingBase<T, true, Owning, Alignment>::scalingBuffer[srcY * ScalingBase<T, true, Owning, Alignment>::bufferWidth + srcX];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -97,15 +97,15 @@ export namespace Crafter {
|
||||||
const float dstCy = (this->scaled.size.y - 1.0) * 0.5;
|
const float dstCy = (this->scaled.size.y - 1.0) * 0.5;
|
||||||
|
|
||||||
// Source center
|
// Source center
|
||||||
const float srcCx = (ScalingBase<true, Owning, Alignment>::bufferWidth - 1.0) * 0.5;
|
const float srcCx = (ScalingBase<T, true, Owning, Alignment>::bufferWidth - 1.0) * 0.5;
|
||||||
const float srcCy = (ScalingBase<true, Owning, Alignment>::bufferHeight - 1.0) * 0.5;
|
const float srcCy = (ScalingBase<T, true, Owning, Alignment>::bufferHeight - 1.0) * 0.5;
|
||||||
|
|
||||||
const float c = std::cos(RotatingBase<true>::rotation);
|
const float c = std::cos(RotatingBase<true>::rotation);
|
||||||
const float s = std::sin(RotatingBase<true>::rotation);
|
const float s = std::sin(RotatingBase<true>::rotation);
|
||||||
|
|
||||||
// Scale factors (destination → source)
|
// Scale factors (destination → source)
|
||||||
const float scaleX = static_cast<float>(ScalingBase<true, Owning, Alignment>::bufferWidth) / dstWidth;
|
const float scaleX = static_cast<float>(ScalingBase<T, true, Owning, Alignment>::bufferWidth) / dstWidth;
|
||||||
const float scaleY = static_cast<float>(ScalingBase<true, Owning, Alignment>::bufferHeight) / dstHeight;
|
const float scaleY = static_cast<float>(ScalingBase<T, true, Owning, Alignment>::bufferHeight) / dstHeight;
|
||||||
|
|
||||||
for (std::uint32_t yB = 0; yB < this->scaled.size.y; ++yB) {
|
for (std::uint32_t yB = 0; yB < this->scaled.size.y; ++yB) {
|
||||||
for (std::uint32_t xB = 0; xB < this->scaled.size.x; ++xB) {
|
for (std::uint32_t xB = 0; xB < this->scaled.size.x; ++xB) {
|
||||||
|
|
@ -122,8 +122,8 @@ export namespace Crafter {
|
||||||
const std::int32_t srcX = static_cast<std::int32_t>(std::round(sx));
|
const std::int32_t srcX = static_cast<std::int32_t>(std::round(sx));
|
||||||
const std::int32_t srcY = static_cast<std::int32_t>(std::round(sy));
|
const std::int32_t srcY = static_cast<std::int32_t>(std::round(sy));
|
||||||
|
|
||||||
if (srcX >= 0 && srcX < ScalingBase<true, Owning, Alignment>::bufferWidth && srcY >= 0 && srcY < ScalingBase<true, Owning, Alignment>::bufferHeight) {
|
if (srcX >= 0 && srcX < ScalingBase<T, true, Owning, Alignment>::bufferWidth && srcY >= 0 && srcY < ScalingBase<T, true, Owning, Alignment>::bufferHeight) {
|
||||||
this->buffer[yB * this->scaled.size.x + xB] = ScalingBase<true, Owning, Alignment>::scalingBuffer[srcY * ScalingBase<true, Owning, Alignment>::bufferWidth + srcX];
|
this->buffer[yB * this->scaled.size.x + xB] = ScalingBase<T, true, Owning, Alignment>::scalingBuffer[srcY * ScalingBase<T, true, Owning, Alignment>::bufferWidth + srcX];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -208,7 +208,7 @@ export namespace Crafter {
|
||||||
size = std::min(maxFontHeight, maxFontWidth);
|
size = std::min(maxFontHeight, maxFontWidth);
|
||||||
} else {
|
} else {
|
||||||
if constexpr(Scaling) {
|
if constexpr(Scaling) {
|
||||||
lines.resize(ScalingBase<true, Owning, Alignment>::bufferHeight / lines.size());
|
lines.resize(ScalingBase<T, true, Owning, Alignment>::bufferHeight / lines.size());
|
||||||
} else {
|
} else {
|
||||||
lines.resize(this->scaled.size.y / lines.size());
|
lines.resize(this->scaled.size.y / lines.size());
|
||||||
}
|
}
|
||||||
|
|
@ -284,7 +284,7 @@ export namespace Crafter {
|
||||||
size = this->scaled.size.y / lineHeightPerFont;
|
size = this->scaled.size.y / lineHeightPerFont;
|
||||||
} else {
|
} else {
|
||||||
if constexpr(Scaling) {
|
if constexpr(Scaling) {
|
||||||
lines.resize(ScalingBase<true, Owning, Alignment>::bufferHeight / lines.size());
|
lines.resize(ScalingBase<T, true, Owning, Alignment>::bufferHeight / lines.size());
|
||||||
} else {
|
} else {
|
||||||
lines.resize(this->scaled.size.y / lines.size());
|
lines.resize(this->scaled.size.y / lines.size());
|
||||||
}
|
}
|
||||||
|
|
@ -293,7 +293,27 @@ export namespace Crafter {
|
||||||
|
|
||||||
return lines;
|
return lines;
|
||||||
}
|
}
|
||||||
void RenderText(std::span<const std::string_view> lines, float size, Vector<std::uint8_t, 4> color, Font& font, TextAlignment alignment = TextAlignment::Left, std::uint32_t offsetX = 0, std::uint32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) {
|
|
||||||
|
int utf8_decode(const char* s, int* bytes_consumed) {
|
||||||
|
unsigned char c = s[0];
|
||||||
|
if (c < 0x80) {
|
||||||
|
*bytes_consumed = 1;
|
||||||
|
return c;
|
||||||
|
} else if ((c & 0xE0) == 0xC0) {
|
||||||
|
*bytes_consumed = 2;
|
||||||
|
return ((c & 0x1F) << 6) | (s[1] & 0x3F);
|
||||||
|
} else if ((c & 0xF0) == 0xE0) {
|
||||||
|
*bytes_consumed = 3;
|
||||||
|
return ((c & 0x0F) << 12) | ((s[1] & 0x3F) << 6) | (s[2] & 0x3F);
|
||||||
|
} else if ((c & 0xF8) == 0xF0) {
|
||||||
|
*bytes_consumed = 4;
|
||||||
|
return ((c & 0x07) << 18) | ((s[1] & 0x3F) << 12) | ((s[2] & 0x3F) << 6) | (s[3] & 0x3F);
|
||||||
|
}
|
||||||
|
*bytes_consumed = 1;
|
||||||
|
return 0xFFFD; // replacement char
|
||||||
|
}
|
||||||
|
|
||||||
|
void RenderText(std::span<const std::string_view> lines, float size, Vector<T, 4> color, Font& font, TextAlignment alignment = TextAlignment::Left, std::uint32_t offsetX = 0, std::uint32_t offsetY = 0, OpaqueType opaque = OpaqueType::FullyOpaque) {
|
||||||
float scale = stbtt_ScaleForPixelHeight(&font.font, size);
|
float scale = stbtt_ScaleForPixelHeight(&font.font, size);
|
||||||
int baseline = (int)(font.ascent * scale);
|
int baseline = (int)(font.ascent * scale);
|
||||||
std::uint32_t lineHeight = (font.ascent - font.descent) * scale;
|
std::uint32_t lineHeight = (font.ascent - font.descent) * scale;
|
||||||
|
|
@ -320,8 +340,13 @@ export namespace Crafter {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (std::size_t i = 0; i < line.size(); ++i) {
|
const char* p = line.data();
|
||||||
int codepoint = line[i];
|
const char* end = p + line.size();
|
||||||
|
|
||||||
|
while (p < end) {
|
||||||
|
int bytes;
|
||||||
|
int codepoint = utf8_decode(p, &bytes);
|
||||||
|
p += bytes;
|
||||||
|
|
||||||
int ax;
|
int ax;
|
||||||
int lsb;
|
int lsb;
|
||||||
|
|
@ -346,12 +371,12 @@ export namespace Crafter {
|
||||||
|
|
||||||
// Only draw pixels that are within our scaled buffer bounds
|
// Only draw pixels that are within our scaled buffer bounds
|
||||||
if constexpr(Scaling) {
|
if constexpr(Scaling) {
|
||||||
if (bufferX >= 0 && bufferX < ScalingBase<true, Owning, Alignment>::bufferWidth && bufferY >= 0 && bufferY < ScalingBase<true, Owning, Alignment>::bufferHeight) {
|
if (bufferX >= 0 && bufferX < ScalingBase<T, true, Owning, Alignment>::bufferWidth && bufferY >= 0 && bufferY < ScalingBase<T, true, Owning, Alignment>::bufferHeight) {
|
||||||
ScalingBase<true, Owning, Alignment>::scalingBuffer[bufferY * ScalingBase<true, Owning, Alignment>::bufferWidth + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
ScalingBase<T, true, Owning, Alignment>::scalingBuffer[bufferY * ScalingBase<T, true, Owning, Alignment>::bufferWidth + bufferX] = {color.r, color.g, color.b, static_cast<T>(bitmap[j * w + i])};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bufferX >= 0 && bufferX < (int)this->scaled.size.x && bufferY >= 0 && bufferY < (int)this->scaled.size.y) {
|
if (bufferX >= 0 && bufferX < (int)this->scaled.size.x && bufferY >= 0 && bufferY < (int)this->scaled.size.y) {
|
||||||
this->buffer[bufferY * this->scaled.size.x + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
this->buffer[bufferY * this->scaled.size.x + bufferX] = {color.r, color.g, color.b, static_cast<T>(bitmap[j * w + i])};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -366,14 +391,14 @@ export namespace Crafter {
|
||||||
|
|
||||||
// Only draw pixels that are within our scaled buffer bounds
|
// Only draw pixels that are within our scaled buffer bounds
|
||||||
if constexpr(Scaling) {
|
if constexpr(Scaling) {
|
||||||
if (bufferX >= 0 && bufferX < ScalingBase<true, Owning, Alignment>::bufferWidth && bufferY >= 0 && bufferY < ScalingBase<true, Owning, Alignment>::bufferHeight) {
|
if (bufferX >= 0 && bufferX < ScalingBase<T, true, Owning, Alignment>::bufferWidth && bufferY >= 0 && bufferY < ScalingBase<T, true, Owning, Alignment>::bufferHeight) {
|
||||||
ScalingBase<true, Owning, Alignment>::scalingBuffer[bufferY * ScalingBase<true, Owning, Alignment>::bufferWidth + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
ScalingBase<T, true, Owning, Alignment>::scalingBuffer[bufferY * ScalingBase<T, true, Owning, Alignment>::bufferWidth + bufferX] = {color.r, color.g, color.b, static_cast<T>(bitmap[j * w + i])};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bufferX >= 0 && bufferX < (int)this->scaled.size.x && bufferY >= 0 && bufferY < (int)this->scaled.size.y) {
|
if (bufferX >= 0 && bufferX < (int)this->scaled.size.x && bufferY >= 0 && bufferY < (int)this->scaled.size.y) {
|
||||||
std::uint8_t alpha = bitmap[j * w + i];
|
std::uint8_t alpha = bitmap[j * w + i];
|
||||||
if(alpha != 0) {
|
if(alpha != 0) {
|
||||||
this->buffer[bufferY * this->scaled.size.x + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
this->buffer[bufferY * this->scaled.size.x + bufferX] = {color.r, color.g, color.b, static_cast<T>(bitmap[j * w + i])};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -389,29 +414,41 @@ export namespace Crafter {
|
||||||
|
|
||||||
// Only draw pixels that are within our scaled buffer bounds
|
// Only draw pixels that are within our scaled buffer bounds
|
||||||
if constexpr(Scaling) {
|
if constexpr(Scaling) {
|
||||||
if (bufferX >= 0 && bufferX < ScalingBase<true, Owning, Alignment>::bufferWidth && bufferY >= 0 && bufferY < ScalingBase<true, Owning, Alignment>::bufferHeight) {
|
if (bufferX >= 0 && bufferX < ScalingBase<T, true, Owning, Alignment>::bufferWidth && bufferY >= 0 && bufferY < ScalingBase<T, true, Owning, Alignment>::bufferHeight) {
|
||||||
ScalingBase<true, Owning, Alignment>::scalingBuffer[bufferY * ScalingBase<true, Owning, Alignment>::bufferWidth + bufferX] = {color.r, color.g, color.b, bitmap[j * w + i]};
|
ScalingBase<T, true, Owning, Alignment>::scalingBuffer[bufferY * ScalingBase<T, true, Owning, Alignment>::bufferWidth + bufferX] = {color.r, color.g, color.b, static_cast<T>(bitmap[j * w + i])};
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bufferX >= 0 && bufferX < (int)this->scaled.size.x && bufferY >= 0 && bufferY < (int)this->scaled.size.y) {
|
if (bufferX >= 0 && bufferX < (int)this->scaled.size.x && bufferY >= 0 && bufferY < (int)this->scaled.size.y) {
|
||||||
std::uint8_t alpha = bitmap[j * w + i];
|
if constexpr(std::same_as<T, std::uint8_t>) {
|
||||||
|
std::uint8_t alpha = bitmap[j * w + i];
|
||||||
|
|
||||||
if(alpha == 0) {
|
Vector<T, 4, Alignment> dst = this->buffer[bufferY * this->scaled.size.x + bufferX];
|
||||||
continue;
|
|
||||||
|
float srcA = (alpha / 255.0f) * (color.a / 255.0f);
|
||||||
|
float dstA = dst.a / 255.0f;
|
||||||
|
|
||||||
|
float oneMinusSrcA = 1.0f - color.a;
|
||||||
|
|
||||||
|
float outA = srcA + dstA * (1.0f - srcA);
|
||||||
|
this->buffer[bufferY * this->scaled.size.x + bufferX] = Vector<std::uint8_t, 4, Alignment>(
|
||||||
|
static_cast<std::uint8_t>((color.r * srcA + dst.r * dstA * (1.0f - srcA)) / outA),
|
||||||
|
static_cast<std::uint8_t>((color.g * srcA + dst.g * dstA * (1.0f - srcA)) / outA),
|
||||||
|
static_cast<std::uint8_t>((color.b * srcA + dst.b * dstA * (1.0f - srcA)) / outA),
|
||||||
|
static_cast<std::uint8_t>(outA * 255)
|
||||||
|
);
|
||||||
|
} else if constexpr(std::same_as<T, _Float16>) {
|
||||||
|
std::uint8_t alpha = bitmap[j * w + i];
|
||||||
|
_Float16 srcA = (_Float16(alpha)/_Float16(255.0f))*color.a;
|
||||||
|
Vector<_Float16, 4, Alignment> dst = this->buffer[bufferY * this->scaled.size.x + bufferX];
|
||||||
|
|
||||||
|
_Float16 outA = srcA + dst.a * (1.0f - srcA);
|
||||||
|
this->buffer[bufferY * this->scaled.size.x + bufferX] = Vector<_Float16, 4, Alignment>(
|
||||||
|
(color.r * srcA + dst.r * dst.a * (1.0f - srcA)),
|
||||||
|
(color.g * srcA + dst.g * dst.a * (1.0f - srcA)),
|
||||||
|
(color.b * srcA + dst.b * dst.a * (1.0f - srcA)),
|
||||||
|
outA
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<std::uint8_t, 4, Alignment> dst = this->buffer[bufferY * this->scaled.size.x + bufferX];
|
|
||||||
|
|
||||||
float srcA = (alpha / 255.0f) * (color.a / 255.0f);
|
|
||||||
float dstA = dst.a / 255.0f;
|
|
||||||
|
|
||||||
float outA = srcA + dstA * (1.0f - srcA);
|
|
||||||
this->buffer[bufferY * this->scaled.size.x + bufferX] = Vector<std::uint8_t, 4, Alignment>(
|
|
||||||
static_cast<std::uint8_t>((color.r * srcA + dst.r * dstA * (1.0f - srcA)) / outA),
|
|
||||||
static_cast<std::uint8_t>((color.g * srcA + dst.g * dstA * (1.0f - srcA)) / outA),
|
|
||||||
static_cast<std::uint8_t>((color.b * srcA + dst.b * dstA * (1.0f - srcA)) / outA),
|
|
||||||
static_cast<std::uint8_t>(outA * 255)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -422,8 +459,9 @@ export namespace Crafter {
|
||||||
|
|
||||||
x += (int)(ax * scale);
|
x += (int)(ax * scale);
|
||||||
|
|
||||||
if (i + 1 < line.size()) {
|
if (p + 1 < end) {
|
||||||
x += (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, line[i+1]);
|
int next;
|
||||||
|
x += (int)stbtt_GetGlyphKernAdvance(&font.font, codepoint, utf8_decode(p+1, &next));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentY += lineHeight;
|
currentY += lineHeight;
|
||||||
|
|
|
||||||
|
|
@ -42,9 +42,9 @@ export namespace Crafter {
|
||||||
Buffer
|
Buffer
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::uint8_t Alignment = 0>
|
template<typename T, std::uint8_t Alignment = 0>
|
||||||
struct RenderElement2DScalingOwning {
|
struct RenderElement2DScalingOwning {
|
||||||
std::vector<Vector<std::uint8_t, 4, Alignment>> scalingBuffer;
|
std::vector<Vector<T, 4, Alignment>> scalingBuffer;
|
||||||
std::uint32_t bufferWidth;
|
std::uint32_t bufferWidth;
|
||||||
std::uint32_t bufferHeight;
|
std::uint32_t bufferHeight;
|
||||||
RenderElement2DScalingOwning() = default;
|
RenderElement2DScalingOwning() = default;
|
||||||
|
|
@ -53,13 +53,13 @@ export namespace Crafter {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<std::uint8_t Alignment = 0>
|
template<typename T, std::uint8_t Alignment = 0>
|
||||||
struct RenderElement2DScalingNonOwning {
|
struct RenderElement2DScalingNonOwning {
|
||||||
Vector<std::uint8_t, 4, Alignment>* scalingBuffer;
|
Vector<T, 4, Alignment>* scalingBuffer;
|
||||||
std::uint32_t bufferWidth;
|
std::uint32_t bufferWidth;
|
||||||
std::uint32_t bufferHeight;
|
std::uint32_t bufferHeight;
|
||||||
RenderElement2DScalingNonOwning() = default;
|
RenderElement2DScalingNonOwning() = default;
|
||||||
RenderElement2DScalingNonOwning(Vector<std::uint8_t, 4, Alignment>* scalingBuffer, std::uint32_t bufferWidth, std::uint32_t bufferHeight) : scalingBuffer(scalingBuffer), bufferWidth(bufferWidth), bufferHeight(bufferHeight) {
|
RenderElement2DScalingNonOwning(Vector<T, 4, Alignment>* scalingBuffer, std::uint32_t bufferWidth, std::uint32_t bufferHeight) : scalingBuffer(scalingBuffer), bufferWidth(bufferWidth), bufferHeight(bufferHeight) {
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -76,13 +76,13 @@ export namespace Crafter {
|
||||||
struct EmptyScalingBase {};
|
struct EmptyScalingBase {};
|
||||||
struct EmptyRotatingBase {};
|
struct EmptyRotatingBase {};
|
||||||
|
|
||||||
template<bool Scaling, bool Owning, std::uint8_t Alignment = 0>
|
template<typename T, bool Scaling, bool Owning, std::uint8_t Alignment = 0>
|
||||||
using ScalingBase =
|
using ScalingBase =
|
||||||
std::conditional_t<
|
std::conditional_t<
|
||||||
Scaling,
|
Scaling,
|
||||||
std::conditional_t<Owning,
|
std::conditional_t<Owning,
|
||||||
RenderElement2DScalingOwning<Alignment>,
|
RenderElement2DScalingOwning<T, Alignment>,
|
||||||
RenderElement2DScalingNonOwning<Alignment>>,
|
RenderElement2DScalingNonOwning<T, Alignment>>,
|
||||||
EmptyScalingBase
|
EmptyScalingBase
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
|
@ -115,7 +115,7 @@ export namespace Crafter {
|
||||||
redraw[i] = true;
|
redraw[i] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void CopyNearestNeighbor(Vector<std::uint8_t, 4>* dst, std::uint16_t dstSizeX, std::uint16_t dstScaledSizeX, std::uint16_t dstScaledSizeY, std::uint16_t offsetX, std::uint16_t offsetY) {
|
void CopyNearestNeighbor(Vector<T, 4>* dst, std::uint16_t dstSizeX, std::uint16_t dstScaledSizeX, std::uint16_t dstScaledSizeY, std::uint16_t offsetX, std::uint16_t offsetY) {
|
||||||
for (std::uint16_t y = 0; y < dstScaledSizeY; y++) {
|
for (std::uint16_t y = 0; y < dstScaledSizeY; y++) {
|
||||||
std::uint16_t srcY = y * scaled.size.y / dstScaledSizeY;
|
std::uint16_t srcY = y * scaled.size.y / dstScaledSizeY;
|
||||||
std::uint16_t dstY = y + offsetY;
|
std::uint16_t dstY = y + offsetY;
|
||||||
|
|
|
||||||
|
|
@ -66,15 +66,20 @@ export namespace Crafter {
|
||||||
dirty.right = std::min(std::uint16_t(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(std::uint16_t(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);
|
||||||
|
|
||||||
|
if(dirty.right <= dirty.left || dirty.bottom <= dirty.top) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const Vector<T, 4, 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::uint16_t src_width = element->scaled.size.x;
|
||||||
std::int32_t src_height = element->scaled.size.y;
|
std::uint16_t src_height = element->scaled.size.y;
|
||||||
|
|
||||||
switch (element->opaque) {
|
switch (element->opaque) {
|
||||||
case OpaqueType::FullyOpaque: {
|
case OpaqueType::FullyOpaque: {
|
||||||
for (std::int32_t y = dirty.top; y < dirty.bottom; y++) {
|
for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) {
|
||||||
std::int32_t src_y = y - element->scaled.position.y;
|
std::uint16_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<T, Channels, Alignment>));
|
std::uint16_t src_x = dirty.left - element->scaled.position.x;
|
||||||
|
std::memcpy(&this->buffer[frame][y * this->sizeX + dirty.left], &src_buffer[src_y * src_width + src_x], (dirty.right - dirty.left) * sizeof(Vector<T, Channels, Alignment>));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -83,20 +88,20 @@ 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::uint32_t pixel_width = dirty.right - dirty.left;
|
std::uint16_t pixel_width = dirty.right - dirty.left;
|
||||||
|
|
||||||
constexpr std::uint32_t simd_width = VectorF16<1, 1>::MaxElement / 4;
|
constexpr std::uint32_t simd_width = VectorF16<1, 1>::MaxElement / 4;
|
||||||
std::uint32_t rows = pixel_width / simd_width;
|
std::uint32_t rows = pixel_width / simd_width;
|
||||||
|
|
||||||
for (std::uint32_t x = 0; x < rows; x++) {
|
for (std::uint32_t x = 0; x < rows; x++) {
|
||||||
std::uint16_t px = dirty.left + x * simd_width;
|
std::uint16_t px = dirty.left + x * simd_width;
|
||||||
std::uint16_t src_x = px - element->scaled.position.x;
|
std::uint16_t src_x = px - element->scaled.position.x;
|
||||||
std::uint16_t dst_x = px;
|
|
||||||
|
|
||||||
VectorF16<4, simd_width> src(&src_buffer[src_y * src_width + src_x].v[0]);
|
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> dst(&buffer[frame][y * this->sizeX + px].v[0]);
|
||||||
VectorF16<4, simd_width> oneMinusSrcA = VectorF16<4, simd_width>(1) - src.Shuffle<{{3, 3, 3, 3}}>();
|
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);
|
VectorF16<4, simd_width> result = VectorF16<4, simd_width>::MulitplyAdd(dst, oneMinusSrcA, src);
|
||||||
result.Store(buffer[frame][y * this->sizeX + dst_x]);
|
result.Store(&buffer[frame][y * this->sizeX + px].v[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint32_t remainder = pixel_width - (rows * simd_width);
|
std::uint32_t remainder = pixel_width - (rows * simd_width);
|
||||||
|
|
@ -108,7 +113,7 @@ export namespace Crafter {
|
||||||
|
|
||||||
Vector<T, Channels, Alignment> src = src_buffer[src_y * src_width + src_x];
|
Vector<T, Channels, Alignment> src = src_buffer[src_y * src_width + src_x];
|
||||||
Vector<T, Channels, Alignment> dst = buffer[frame][y * this->sizeX + px];
|
Vector<T, Channels, Alignment> dst = buffer[frame][y * this->sizeX + px];
|
||||||
_Float16 oneMinusSrcA = (_Float16)1.0f - src[3];
|
_Float16 oneMinusSrcA = (_Float16)1.0f - src.a;
|
||||||
|
|
||||||
buffer[frame][y * this->sizeX + px] = Vector<T, Channels, Alignment>(
|
buffer[frame][y * this->sizeX + px] = Vector<T, Channels, Alignment>(
|
||||||
src.r + dst.r * oneMinusSrcA,
|
src.r + dst.r * oneMinusSrcA,
|
||||||
|
|
@ -119,9 +124,10 @@ export namespace Crafter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (std::int32_t y = dirty.top; y < dirty.bottom; y++) {
|
for (std::uint16_t y = dirty.top; y < dirty.bottom; y++) {
|
||||||
std::int32_t src_y = y - element->scaled.position.y;
|
std::uint16_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<T, Channels, Alignment>));
|
std::uint16_t src_x = dirty.left - element->scaled.position.x;
|
||||||
|
std::memcpy(&this->buffer[frame][y * this->sizeX + dirty.left], &src_buffer[src_y * src_width + src_x], (dirty.right - dirty.left) * sizeof(Vector<T, Channels, Alignment>));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue