commit x64 compilation from lulu cause the other branch dont seems to compile properly at home

This commit is contained in:
2026-07-17 16:08:20 +02:00
parent c0f3eeb00d
commit 0efa4ee6f7
625 changed files with 117283 additions and 4426 deletions

View File

@ -0,0 +1,539 @@
#include "gpu/gpu_types.h"
#include "gpu/gpu_renderer.h"
#include "log/log.h"
#include "math/nmath.h"
#include "memory/memory.h"
using namespace GS;
using namespace GS::GPU;
//------------------------------------------------------------------------------
Render::Texture *Renderer::CreateRenderTexture(
const char *name,
uint width,
uint height,
Render::Texture::Format format,
Render::Texture::AA aa
)
{
__NTRACE("CreateRenderTexture")
// __LOG_W__ << "CreateRenderTexture: name=" << name << ", size=" << width << "x" << height << "\n";
Render::Texture *tex = NewTexture(name);
if (!tex)
{
__LOG_E__ << "CreateRenderTexture: NewTexture failed!\n";
return nullptr;
}
// __LOG_W__ << "CreateRenderTexture: NewTexture succeeded, tex ptr=" << (void*)tex << "\n";
const Render::Texture::Usage usage =
Render::Texture::Usage(
Render::Texture::IsRenderTarget |
Render::Texture::IsShaderResource
);
// __LOG_W__ << "CreateRenderTexture: Calling tex->Create with format=" << format << ", aa=" << aa << "\n";
if (tex->Create(nullptr, width, height, format, aa, usage))
{
// __LOG_W__ << "CreateRenderTexture: Success! Returning texture.\n";
return tex;
}
__LOG_E__ << "CreateRenderTexture: tex->Create failed!\n";
tex->Free();
return nullptr;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Renderer::ClearTexture(Render::Texture *target, const Color &clear_color)
{
__NTRACE("ClearTexture")
// __LOG_W__ << "ClearTexture: Clearing target texture with color (" << clear_color.x << ", " << clear_color.y << ", " << clear_color.z << ", " << clear_color.w << ")\n";
if (!target)
{
__LOG_E__ << "ClearTexture: target is null!\n";
return;
}
const uint tex_w = target->GetWidth();
const uint tex_h = target->GetHeight();
// Use DrawSplineToTexture with clear_target=true to clear the texture
// This is a workaround since Blit() doesn't work on RenderTarget textures
// __LOG_W__ << "ClearTexture: Using DrawSplineToTexture method with clear...\n";
// Create a dummy 2-point array (not used since we're clearing)
Array<Vector2> dummy_points;
dummy_points.Allocate(2);
dummy_points[0] = Vector2(0, 0);
dummy_points[1] = Vector2(1, 1);
// Call DrawSplineToTexture with clear_target=true and zero width (no drawing)
// This will fill the buffer with the clear color
const uint pitch = tex_w * 4;
const size_t buffer_size = pitch * tex_h;
unsigned char *pixels = new unsigned char[buffer_size];
// Convert color to 8-bit RGBA
const auto r = (unsigned char)(clear_color.x * 255.0f);
const auto g = (unsigned char)(clear_color.y * 255.0f);
const auto b = (unsigned char)(clear_color.z * 255.0f);
const auto a = (unsigned char)(clear_color.w * 255.0f);
// __LOG_W__ << "ClearTexture: Filling buffer with RGBA(" << (int)r << ", " << (int)g << ", " << (int)b << ", " << (int)a << ")...\n";
// Fill with clear color (ABGR format)
unsigned int pixel_value = (a << 24) | (b << 16) | (g << 8) | r;
unsigned int *pixel_buffer = (unsigned int *)pixels;
for (uint i = 0; i < tex_w * tex_h; ++i)
{
pixel_buffer[i] = pixel_value;
}
// __LOG_W__ << "ClearTexture: Uploading via Blit...\n";
target->Blit((const char *)pixels, tex_w, tex_h, 0, 0, Render::Texture::FormatRGBA8);
delete[] pixels;
// __LOG_W__ << "ClearTexture: Complete!\n";
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Renderer::BlitTextureToTexture(
Render::Texture *src,
Render::Texture *dst,
const fRect *src_rect,
const fRect *dst_rect
)
{
__NTRACE("BlitTextureToTexture")
if (!src || !dst)
return;
// Default rectangles (full texture)
const fRect src_r = src_rect ? *src_rect : fRect(0, 0, 1, 1);
const fRect dst_r = dst_rect ? *dst_rect : fRect(0, 0, 1, 1);
// Save current state
const fRect old_viewport = viewport;
// Setup FBO for destination
fx_fbo->SetColorTexture(dst);
fx_fbo->SetDepthTexture(nullptr);
SetCurrentFBO(fx_fbo);
SetViewport(fRect(0, 0, (float)dst->GetWidth(), (float)dst->GetHeight()));
// Use existing RenderFullscreenQuad infrastructure
RenderFullscreenQuad(*single_texture_program, src_r, dst_r, src);
// Restore state
SetCurrentFBO(nullptr);
SetViewport(old_viewport);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Vector2 Renderer::CatmullRomInterpolate(
const Vector2 &p0,
const Vector2 &p1,
const Vector2 &p2,
const Vector2 &p3,
float t
) const
{
// Catmull-Rom spline with tau = 0.5
const float t2 = t * t;
const float t3 = t2 * t;
// Manual calculation for Vector2
Vector2 result;
result.x = 0.5f * (
(2.0f * p1.x) +
(-p0.x + p2.x) * t +
(2.0f * p0.x - 5.0f * p1.x + 4.0f * p2.x - p3.x) * t2 +
(-p0.x + 3.0f * p1.x - 3.0f * p2.x + p3.x) * t3
);
result.y = 0.5f * (
(2.0f * p1.y) +
(-p0.y + p2.y) * t +
(2.0f * p0.y - 5.0f * p1.y + 4.0f * p2.y - p3.y) * t2 +
(-p0.y + 3.0f * p1.y - 3.0f * p2.y + p3.y) * t3
);
return result;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Renderer::TessellateSplineRibbon(
const Array<Vector2> &control_points,
float width_normalized,
const Color &color,
int samples_per_segment,
bool soft_edge,
SplineRibbon &out_ribbon
)
{
__NTRACE("TessellateSplineRibbon")
const int num_control = control_points.GetCount();
if (num_control < 2)
return;
// For Catmull-Rom: we have num_control-1 segments
const int num_segments = num_control - 1;
if (num_segments < 1)
return;
// Allocate arrays for sampled points
const int total_samples = num_segments * samples_per_segment + 1;
Array<Vector2> samples;
Array<Vector2> tangents;
samples.Allocate(total_samples);
tangents.Allocate(total_samples);
// Sample the spline using Catmull-Rom interpolation
int sample_idx = 0;
for (int seg = 0; seg < num_segments; seg++)
{
// Get 4 control points (with duplication at boundaries)
Vector2 p0 = (seg > 0) ? control_points[seg - 1] : control_points[seg];
Vector2 p1 = control_points[seg];
Vector2 p2 = control_points[seg + 1];
Vector2 p3 = (seg < num_segments - 1) ? control_points[seg + 2] : control_points[seg + 1];
for (int s = 0; s < samples_per_segment; s++)
{
const float t = (float)s / (float)samples_per_segment;
samples[sample_idx] = CatmullRomInterpolate(p0, p1, p2, p3, t);
// Compute tangent (derivative approximation)
const float dt = 0.01f;
const float t_next = (t + dt > 1.0f) ? 1.0f : t + dt;
Vector2 p_next = CatmullRomInterpolate(p0, p1, p2, p3, t_next);
Vector2 diff = p_next - samples[sample_idx];
tangents[sample_idx] = diff.Normalized();
sample_idx++;
}
}
// Add final point
samples[total_samples - 1] = control_points[num_control - 1];
tangents[total_samples - 1] = tangents[total_samples - 2]; // Reuse last tangent
// Build ribbon geometry
out_ribbon.positions.Allocate(total_samples * 2);
out_ribbon.colors.Allocate(total_samples * 2);
for (int i = 0; i < total_samples; i++)
{
const Vector2 pos = samples[i];
const Vector2 tangent = tangents[i];
// Perpendicular normal (2D rotation by 90 degrees)
Vector2 normal(-tangent.y, tangent.x);
// Convert from normalized [0..1] texture space to clip space [-1..1]
const float x_clip = pos.x * 2.0f - 1.0f;
const float y_clip = 1.0f - pos.y * 2.0f; // Flip Y (texture origin top-left)
// Offset in clip space
const Vector2 offset = normal * width_normalized;
// Left and right vertices
out_ribbon.positions[i * 2 + 0] = Vector4(
x_clip - offset.x,
y_clip - offset.y,
0.0f,
1.0f
);
out_ribbon.positions[i * 2 + 1] = Vector4(
x_clip + offset.x,
y_clip + offset.y,
0.0f,
1.0f
);
// Colors with soft edge via alpha gradient
if (soft_edge)
{
// Apply alpha gradient on outer edges (30% opacity) vs center (full opacity)
// But since we're using a ribbon with 2 vertices per sample, both get same alpha
// To get true soft edge, we'd need a center vertex too, but for now just use the color as-is
// TODO: Implement true soft edge with centerline vertex if needed
out_ribbon.colors[i * 2 + 0] = color;
out_ribbon.colors[i * 2 + 1] = color;
}
else
{
out_ribbon.colors[i * 2 + 0] = color;
out_ribbon.colors[i * 2 + 1] = color;
}
}
// Build indices (triangle list)
const int num_quads = total_samples - 1;
out_ribbon.indices.Allocate(num_quads * 6);
for (int i = 0; i < num_quads; i++)
{
const ushort i0 = (ushort)(i * 2);
const ushort i1 = (ushort)(i * 2 + 1);
const ushort i2 = (ushort)((i + 1) * 2);
const ushort i3 = (ushort)((i + 1) * 2 + 1);
// Triangle 1
out_ribbon.indices[i * 6 + 0] = i0;
out_ribbon.indices[i * 6 + 1] = i2;
out_ribbon.indices[i * 6 + 2] = i1;
// Triangle 2
out_ribbon.indices[i * 6 + 3] = i1;
out_ribbon.indices[i * 6 + 4] = i2;
out_ribbon.indices[i * 6 + 5] = i3;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Helper: Draw a simple line to texture pixel data (Bresenham-like)
static void DrawLineToPixels(unsigned char *pixels, uint width, uint height, uint pitch,
int x0, int y0, int x1, int y1,
unsigned char r, unsigned char g, unsigned char b, unsigned char a)
{
const int dx = abs(x1 - x0);
const int dy = abs(y1 - y0);
const int sx = (x0 < x1) ? 1 : -1;
const int sy = (y0 < y1) ? 1 : -1;
int err = dx - dy;
int x = x0, y = y0;
while (true)
{
if (x >= 0 && x < (int)width && y >= 0 && y < (int)height)
{
int *pixel = (int*)(pixels + y * pitch + x * 4);
// Read destination pixel components (packed as in existing code: ABGR)
const unsigned int dst = *pixel;
const unsigned char dst_r = (unsigned char)(dst & 0xFF);
const unsigned char dst_g = (unsigned char)((dst >> 8) & 0xFF);
const unsigned char dst_b = (unsigned char)((dst >> 16) & 0xFF);
const unsigned char dst_a = (unsigned char)((dst >> 24) & 0xFF);
// Source alpha (0..1)
const float src_af = (float)a / 255.0f;
const float inv = 1.0f - src_af;
// Standard 'over' compositing: out = src*src_a + dst*(1-src_a)
const unsigned char out_r = (unsigned char)(r * src_af + dst_r * inv + 0.5f);
const unsigned char out_g = (unsigned char)(g * src_af + dst_g * inv + 0.5f);
const unsigned char out_b = (unsigned char)(b * src_af + dst_b * inv + 0.5f);
const unsigned char out_a = (unsigned char)(a + dst_a * inv + 0.5f);
*pixel = (out_a << 24) | (out_b << 16) | (out_g << 8) | out_r; // ABGR packing (kept as original)
}
if (x == x1 && y == y1) break;
const int e2 = 2 * err;
if (e2 > -dy) { err -= dy; x += sx; }
if (e2 < dx) { err += dx; y += sy; }
}
}
void Renderer::DrawSplineToTexture(
Render::Texture *target,
const Array<Vector2> &control_points,
float width_pixels,
const Color &color,
int samples_per_segment,
bool clear_target,
bool soft_edge,
const Color *border_color,
float border_width,
float margin
)
{
__NTRACE("DrawSplineToTexture")
// __LOG_W__ << "Drawing spline to texture (CPU-based method)...\n";
if (!target) {
__LOG_E__ << "DrawSplineToTexture: target texture is null!\n";
return;
}
if (control_points.GetCount() < 2) {
__LOG_E__ << "DrawSplineToTexture: not enough control points!\n";
return;
}
const uint tex_w = target->GetWidth();
const uint tex_h = target->GetHeight();
// __LOG_W__ << "Target texture size: " << tex_w << "x" << tex_h << "\n";
// Convert color to 8-bit RGBA
const auto r = (unsigned char)(color.x * 255.0f);
const auto g = (unsigned char)(color.y * 255.0f);
const auto b = (unsigned char)(color.z * 255.0f);
const auto a = (unsigned char)(color.w * 255.0f);
// __LOG_W__ << "Color: R=" << (int)r << " G=" << (int)g << " B=" << (int)b << " A=" << (int)a << "\n";
// Convert border color if provided
unsigned char border_r = 0, border_g = 0, border_b = 0, border_a = 0;
if (border_color && border_width > 0.0f) {
border_r = (unsigned char)(border_color->x * 255.0f);
border_g = (unsigned char)(border_color->y * 255.0f);
border_b = (unsigned char)(border_color->z * 255.0f);
border_a = (unsigned char)(border_color->w * 255.0f);
// __LOG_W__ << "Border Color: R=" << (int)border_r << " G=" << (int)border_g << " B=" << (int)border_b << " A=" << (int)border_a << " Width=" << border_width << "\n";
}
const int num_control = control_points.GetCount();
const int num_segments = num_control - 1;
// Adjust control points with margin to avoid clipping
Array<Vector2> adjusted_points;
adjusted_points.Allocate(num_control);
if (margin > 0.0f) {
// __LOG_W__ << "Applying margin: " << margin << "\n";
// Calculate the margin in normalized coordinates [0..1]
const float margin_x = margin / (float)tex_w;
const float margin_y = margin / (float)tex_h;
// Scale and offset control points to fit within margin bounds
float min_x = 1.0f, max_x = 0.0f, min_y = 1.0f, max_y = 0.0f;
for (int i = 0; i < num_control; i++) {
if (control_points[i].x < min_x) min_x = control_points[i].x;
if (control_points[i].x > max_x) max_x = control_points[i].x;
if (control_points[i].y < min_y) min_y = control_points[i].y;
if (control_points[i].y > max_y) max_y = control_points[i].y;
}
const float range_x = max_x - min_x;
const float range_y = max_y - min_y;
const float scale_x = (range_x > 0.0f) ? (1.0f - 2.0f * margin_x) / range_x : 1.0f;
const float scale_y = (range_y > 0.0f) ? (1.0f - 2.0f * margin_y) / range_y : 1.0f;
for (int i = 0; i < num_control; i++) {
adjusted_points[i].x = margin_x + (control_points[i].x - min_x) * scale_x;
adjusted_points[i].y = margin_y + (control_points[i].y - min_y) * scale_y;
}
} else {
// No margin, use original points
for (int i = 0; i < num_control; i++) {
adjusted_points[i] = control_points[i];
}
}
Array<Vector2> samples;
samples.Allocate(num_segments * samples_per_segment + 1);
// Sample the spline using Catmull-Rom interpolation with adjusted points
int sample_idx = 0;
for (int seg = 0; seg < num_segments; seg++)
{
Vector2 p0 = (seg > 0) ? adjusted_points[seg - 1] : adjusted_points[seg];
Vector2 p1 = adjusted_points[seg];
Vector2 p2 = adjusted_points[seg + 1];
Vector2 p3 = (seg < num_segments - 1) ? adjusted_points[seg + 2] : adjusted_points[seg + 1];
for (int s = 0; s < samples_per_segment; s++)
{
const float t = (float)s / (float)samples_per_segment;
samples[sample_idx] = CatmullRomInterpolate(p0, p1, p2, p3, t);
sample_idx++;
}
}
samples[num_segments * samples_per_segment] = adjusted_points[num_control - 1];
// __LOG_W__ << "Generated " << samples.GetCount() << " sampled points\n";
// Create pixel buffer for drawing
// __LOG_W__ << "Creating pixel buffer for CPU rendering...\n";
const uint pitch = tex_w * 4; // RGBA = 4 bytes per pixel
const size_t buffer_size = pitch * tex_h;
unsigned char *pixels = new unsigned char[buffer_size];
// __LOG_W__ << "Pixel buffer created. Size=" << buffer_size << " Pitch=" << pitch << "\n";
if (clear_target)
{
// Initialize with transparent black
memset(pixels, 0, buffer_size);
}
else
{
// Read back the existing texture contents into the buffer so we can composite on top.
// __LOG_W__ << "Reading existing texture pixels into buffer (for compositing)...\n";
// Setup FBO for readback
fx_fbo->SetColorTexture(target);
fx_fbo->SetDepthTexture(nullptr);
SetCurrentFBO(fx_fbo);
fx_fbo->ReadColorPixels((char*)pixels, 0, 0, tex_w, tex_h);
// Restore
SetCurrentFBO(nullptr);
}
// __LOG_W__ << "Drawing spline lines...\n";
// Draw border first (if specified)
if (border_color && border_width > 0.0f) {
// __LOG_W__ << "Drawing border with width: " << border_width << "\n";
const float total_width = width_pixels + border_width * 2.0f;
for (uint i = 0; i + 1 < samples.GetCount(); i++)
{
const int x0 = (int)(samples[i].x * (float)tex_w);
const int y0 = (int)(samples[i].y * (float)tex_h);
const int x1 = (int)(samples[i + 1].x * (float)tex_w);
const int y1 = (int)(samples[i + 1].y * (float)tex_h);
for (int w = -(int)total_width/2; w <= (int)total_width/2; w++)
{
DrawLineToPixels(pixels, tex_w, tex_h, pitch,
x0 + w, y0, x1 + w, y1, border_r, border_g, border_b, border_a);
}
}
}
// Draw main spline on top
for (uint i = 0; i + 1 < samples.GetCount(); i++)
{
// Convert from normalized [0..1] to pixel coordinates
const int x0 = (int)(samples[i].x * (float)tex_w);
const int y0 = (int)(samples[i].y * (float)tex_h);
const int x1 = (int)(samples[i + 1].x * (float)tex_w);
const int y1 = (int)(samples[i + 1].y * (float)tex_h);
// Draw line with width by drawing multiple parallel lines
for (int w = -(int)width_pixels/2; w <= (int)width_pixels/2; w++)
{
DrawLineToPixels(pixels, tex_w, tex_h, pitch,
x0 + w, y0, x1 + w, y1, r, g, b, a);
}
}
// __LOG_W__ << "Uploading pixel buffer to texture...\n";
// Upload to texture using Blit
target->Blit((const char *)pixels, tex_w, tex_h, 0, 0, Render::Texture::FormatRGBA8);
// __LOG_W__ << "Freeing pixel buffer...\n";
delete[] pixels;
// __LOG_W__ << "Buffer freed!\n";
// __LOG_W__ << "DrawSplineToTexture complete!\n";
}
//------------------------------------------------------------------------------