optimizations
This commit is contained in:
parent
b41ec7960c
commit
4925bd77b9
2 changed files with 77 additions and 26 deletions
|
|
@ -134,20 +134,8 @@ void WindowWayland::StartSync() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optimized pixel blending function using SIMD-like operations
|
||||||
|
inline void blend_pixel_optimized(Pixel_BU8_GU8_RU8_AU8& dst, const Pixel_BU8_GU8_RU8_AU8& src) {
|
||||||
void WindowWayland::RenderElement(Transform* transform) {
|
|
||||||
RenderingElement* element = dynamic_cast<RenderingElement*>(transform);
|
|
||||||
if(element) {
|
|
||||||
#ifdef CRAFTER_TIMING
|
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
|
||||||
#endif
|
|
||||||
for (std::int_fast32_t x = element->scaled.x; x - element->scaled.x < element->scaled.width; x++) {
|
|
||||||
for (std::int_fast32_t y = element->scaled.y; y - element->scaled.y < element->scaled.height; y++) {
|
|
||||||
if (x >= 0 && x < width && y >= 0 && y < height) {
|
|
||||||
Pixel_BU8_GU8_RU8_AU8& dst = framebuffer[y * width + x];
|
|
||||||
const Pixel_BU8_GU8_RU8_AU8& src = element->bufferScaled[(y - element->scaled.y) * element->scaled.width + (x - element->scaled.x)];
|
|
||||||
|
|
||||||
float srcA = src.a / 255.0f;
|
float srcA = src.a / 255.0f;
|
||||||
float dstA = dst.a / 255.0f;
|
float dstA = dst.a / 255.0f;
|
||||||
|
|
||||||
|
|
@ -161,8 +149,55 @@ void WindowWayland::RenderElement(Transform* transform) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optimized rendering with bounds checking and early exit
|
||||||
|
void WindowWayland::RenderElement(Transform* transform) {
|
||||||
|
RenderingElement* element = dynamic_cast<RenderingElement*>(transform);
|
||||||
|
if(element) {
|
||||||
|
#ifdef CRAFTER_TIMING
|
||||||
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Calculate clipping bounds
|
||||||
|
std::int_fast32_t clip_left = std::max(element->scaled.x, std::int_fast32_t(0));
|
||||||
|
std::int_fast32_t clip_top = std::max(element->scaled.y, std::int_fast32_t(0));
|
||||||
|
std::int_fast32_t clip_right = std::min(element->scaled.x + element->scaled.width, static_cast<std::int_fast32_t>(width));
|
||||||
|
std::int_fast32_t clip_bottom = std::min(element->scaled.y + element->scaled.height, static_cast<std::int_fast32_t>(height));
|
||||||
|
|
||||||
|
// Early exit if completely outside screen
|
||||||
|
if (clip_left >= clip_right || clip_top >= clip_bottom) {
|
||||||
|
#ifdef CRAFTER_TIMING
|
||||||
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
|
renderTimings.push_back({element, element->scaled.width, element->scaled.height, end-start});
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get source buffer data
|
||||||
|
const Pixel_BU8_GU8_RU8_AU8* src_buffer = element->bufferScaled.data();
|
||||||
|
std::uint_fast32_t src_width = element->scaled.width;
|
||||||
|
std::uint_fast32_t src_height = element->scaled.height;
|
||||||
|
|
||||||
|
// Render clipped region
|
||||||
|
for (std::int_fast32_t y = clip_top; y < clip_bottom; y++) {
|
||||||
|
std::int_fast32_t src_y = y - element->scaled.y;
|
||||||
|
|
||||||
|
for (std::int_fast32_t x = clip_left; x < clip_right; x++) {
|
||||||
|
std::int_fast32_t src_x = x - element->scaled.x;
|
||||||
|
|
||||||
|
// Bounds check for source buffer
|
||||||
|
if (src_x >= 0 && src_x < static_cast<std::int_fast32_t>(src_width) && src_y >= 0 && src_y < static_cast<std::int_fast32_t>(src_height)) {
|
||||||
|
|
||||||
|
// Get pixel indices
|
||||||
|
std::uint_fast32_t dst_idx = y * width + x;
|
||||||
|
std::uint_fast32_t src_idx = src_y * src_width + src_x;
|
||||||
|
|
||||||
|
// Blend pixels
|
||||||
|
blend_pixel_optimized(framebuffer[dst_idx], src_buffer[src_idx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CRAFTER_TIMING
|
#ifdef CRAFTER_TIMING
|
||||||
auto end = std::chrono::high_resolution_clock::now();
|
auto end = std::chrono::high_resolution_clock::now();
|
||||||
renderTimings.push_back({element, element->scaled.width, element->scaled.height, end-start});
|
renderTimings.push_back({element, element->scaled.width, element->scaled.height, end-start});
|
||||||
|
|
@ -178,11 +213,8 @@ void WindowWayland::RenderElement(Transform* transform) {
|
||||||
void WindowWayland::Render() {
|
void WindowWayland::Render() {
|
||||||
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
|
std::sort(elements.begin(), elements.end(), [](Transform* a, Transform* b){ return a->z < b->z; });
|
||||||
|
|
||||||
for (std::uint_fast32_t x = 0; x < width; x++) {
|
// Clear screen efficiently using memset
|
||||||
for (std::uint_fast32_t y = 0; y < height; y++) {
|
memset(framebuffer, 0, width * height * sizeof(Pixel_BU8_GU8_RU8_AU8));
|
||||||
framebuffer[y * width + x] = {0,0,0,0};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Transform* child : elements) {
|
for(Transform* child : elements) {
|
||||||
RenderElement(child);
|
RenderElement(child);
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,27 @@ namespace Crafter {
|
||||||
std::vector<Keyframe<T>> keyframes;
|
std::vector<Keyframe<T>> keyframes;
|
||||||
std::uint_fast32_t currentFrame;
|
std::uint_fast32_t currentFrame;
|
||||||
std::chrono::time_point<std::chrono::high_resolution_clock> startedAt;
|
std::chrono::time_point<std::chrono::high_resolution_clock> startedAt;
|
||||||
Animation(std::vector<Keyframe<T>>&& keyframes) : keyframes(std::move(keyframes)) {}
|
mutable T cachedValue; // Cache the last computed value
|
||||||
|
mutable std::chrono::time_point<std::chrono::high_resolution_clock> lastTime; // Track when cached value was computed
|
||||||
|
|
||||||
|
Animation(std::vector<Keyframe<T>>&& keyframes) : keyframes(std::move(keyframes)), currentFrame(0) {}
|
||||||
|
|
||||||
void Start(std::chrono::time_point<std::chrono::high_resolution_clock> time) {
|
void Start(std::chrono::time_point<std::chrono::high_resolution_clock> time) {
|
||||||
currentFrame = 0;
|
currentFrame = 0;
|
||||||
startedAt = time;
|
startedAt = time;
|
||||||
|
// Invalidate cache
|
||||||
|
lastTime = std::chrono::time_point<std::chrono::high_resolution_clock>();
|
||||||
}
|
}
|
||||||
|
|
||||||
T Play(std::chrono::time_point<std::chrono::high_resolution_clock> time) {
|
T Play(std::chrono::time_point<std::chrono::high_resolution_clock> time) {
|
||||||
|
// Check if we can reuse cached value
|
||||||
|
if (lastTime != std::chrono::time_point<std::chrono::high_resolution_clock>()) {
|
||||||
|
// Only use cached value if we haven't moved forward in time
|
||||||
|
if (time <= lastTime) {
|
||||||
|
return cachedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::chrono::duration<double> elapsed = time - startedAt; // elapsed time since animation started
|
std::chrono::duration<double> elapsed = time - startedAt; // elapsed time since animation started
|
||||||
std::chrono::duration<double> accumulated(0);
|
std::chrono::duration<double> accumulated(0);
|
||||||
|
|
||||||
|
|
@ -77,17 +92,21 @@ namespace Crafter {
|
||||||
auto t = (elapsed - frameStartTime) / keyframes[i+1].duration.count();
|
auto t = (elapsed - frameStartTime) / keyframes[i+1].duration.count();
|
||||||
|
|
||||||
currentFrame = i;
|
currentFrame = i;
|
||||||
return LerpTuple(
|
cachedValue = LerpTuple(
|
||||||
keyframes[i].values,
|
keyframes[i].values,
|
||||||
keyframes[i + 1].values,
|
keyframes[i + 1].values,
|
||||||
t.count()
|
t.count()
|
||||||
);
|
);
|
||||||
|
lastTime = time;
|
||||||
|
return cachedValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, we're past the last keyframe
|
// If we get here, we're past the last keyframe
|
||||||
currentFrame = keyframes.size() - 1;
|
currentFrame = keyframes.size() - 1;
|
||||||
return keyframes.back().values;
|
cachedValue = keyframes.back().values;
|
||||||
|
lastTime = time;
|
||||||
|
return cachedValue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue