chore: auto-commit (95 archivos)
- cmd/fn/doctor.go - cmd/fn/main.go - cpp/apps/primitives_gallery/playground/tables/CMakeLists.txt - cpp/apps/primitives_gallery/playground/tables/data_table.cpp - cpp/apps/primitives_gallery/playground/tables/data_table_logic.cpp - cpp/apps/primitives_gallery/playground/tables/data_table_logic.h - cpp/apps/primitives_gallery/playground/tables/self_test.cpp - cpp/apps/primitives_gallery/playground/tables/tql.cpp - cpp/apps/primitives_gallery/playground/tables/viz.cpp - cpp/apps/primitives_gallery/playground/tables/viz.h - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,212 @@
|
||||
// data_table_types — types compartidos del stack TQL (Table Query Language).
|
||||
// Promovido al registry desde cpp/apps/primitives_gallery/playground/tables/.
|
||||
// Ver issue 0081 + docs/TQL.md. Pure value types + enums.
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace data_table {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Operadores de filtro.
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class Op {
|
||||
Eq, Neq, Gt, Gte, Lt, Lte,
|
||||
Contains, NotContains, StartsWith, EndsWith
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Tipo de columna. Declarado por caller o auto-detectado.
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class ColumnType {
|
||||
Auto, String, Int, Float, Bool, Date, Json
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Derived column: inmutable. Dos modos:
|
||||
// 1) Retipo puro: source_col >= 0, formula == "". Cells del origen.
|
||||
// 2) Formula: source_col == -1, formula no vacia. Eval por Lua.
|
||||
// ----------------------------------------------------------------------------
|
||||
struct DerivedColumn {
|
||||
int source_col = -1;
|
||||
ColumnType type = ColumnType::String;
|
||||
std::string name;
|
||||
std::string formula; // "" = retipado puro; resto = body Lua
|
||||
int lua_id = -1; // referencia en lua_engine; -1 si no compilado
|
||||
std::string compile_error;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Filtro: col index en eff_headers + op + value.
|
||||
// ----------------------------------------------------------------------------
|
||||
struct Filter {
|
||||
int col;
|
||||
Op op;
|
||||
std::string value;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ColorRule: pintado condicional de celdas (UI helper).
|
||||
// ----------------------------------------------------------------------------
|
||||
struct ColorRule {
|
||||
int col;
|
||||
std::string equals;
|
||||
unsigned int color;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Aggregations (TQL stages 1+).
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class AggFn {
|
||||
Count, Sum, Avg, Min, Max, Distinct, Stddev,
|
||||
Median, P25, P75, P90, P99, Percentile
|
||||
};
|
||||
|
||||
struct Aggregation {
|
||||
AggFn fn = AggFn::Count;
|
||||
std::string col; // ignorado para Count
|
||||
double arg = 0.0; // para Percentile (0..1)
|
||||
std::string alias; // vacio -> auto-generado via aggregation_alias()
|
||||
};
|
||||
|
||||
struct SortClause {
|
||||
std::string col;
|
||||
bool desc = false;
|
||||
};
|
||||
|
||||
// Stage: layer de TQL. Stage 0 = Raw (sin breakouts/aggregations).
|
||||
// Stage 1+ pueden agrupar. Cada stage consume output del anterior.
|
||||
struct Stage {
|
||||
std::vector<Filter> filters;
|
||||
std::vector<DerivedColumn> derived; // expressions de este stage
|
||||
std::vector<std::string> breakouts; // col names del INPUT de este stage
|
||||
std::vector<Aggregation> aggregations;
|
||||
std::vector<SortClause> sorts;
|
||||
};
|
||||
|
||||
// Output de compute_stage. Posee `cell_backing` (strings nuevos para
|
||||
// resultados agregados) y `cells` (punteros row-major a backing o a
|
||||
// `in_cells` original para passthrough).
|
||||
struct StageOutput {
|
||||
std::vector<std::string> cell_backing;
|
||||
std::vector<const char*> cells;
|
||||
int rows = 0;
|
||||
int cols = 0;
|
||||
std::vector<std::string> headers;
|
||||
std::vector<ColumnType> types;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ViewMode: tipo de visualizacion a renderizar sobre el output del stage activo.
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class ViewMode {
|
||||
Table,
|
||||
// Bars
|
||||
Bar, Column, GroupedBar, StackedBar,
|
||||
// Lines / area
|
||||
Line, Area, Stairs,
|
||||
// Points
|
||||
Scatter, Bubble,
|
||||
// Distribution
|
||||
Histogram, Histogram2D, Heatmap, BoxPlot,
|
||||
// Stems / signals
|
||||
Stem, ErrorBars,
|
||||
// Composition
|
||||
Pie, Donut, Funnel, Waterfall,
|
||||
// Single values
|
||||
KPI, KPIGrid,
|
||||
// Specialized
|
||||
Candlestick, Radar,
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Joins (MBQL-style). Ver issue 0078.
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class JoinStrategy { Left, Inner, Right, Full };
|
||||
|
||||
// Tabla extra pasada al render() para joins. Owner externo (caller).
|
||||
struct TableInput {
|
||||
std::string name; // identificador estable (matchea Join.source)
|
||||
std::vector<std::string> headers;
|
||||
std::vector<ColumnType> types;
|
||||
const char* const* cells = nullptr; // row-major, headers.size() cols x rows filas
|
||||
int rows = 0;
|
||||
int cols = 0;
|
||||
};
|
||||
|
||||
// Join clause: une la tabla actual con `source` por las parejas `on`,
|
||||
// prefijando las cols del derecho con `alias.`.
|
||||
struct Join {
|
||||
std::string alias;
|
||||
std::string source;
|
||||
std::vector<std::pair<std::string, std::string>> on; // {left_col, right_col}
|
||||
JoinStrategy strategy = JoinStrategy::Left;
|
||||
std::vector<std::string> fields; // vacio = all del derecho
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// ViewConfig: overrides manuales de auto-detect para la vista activa.
|
||||
// ----------------------------------------------------------------------------
|
||||
struct ViewConfig {
|
||||
std::string x_col; // single: scatter, line, hist2d
|
||||
std::vector<std::string> y_cols; // 1..N: line/area/bar/etc
|
||||
std::string size_col; // bubble
|
||||
std::string cat_col; // bar/pie/funnel/box override
|
||||
unsigned int primary_color = 0; // 0 = ImPlot auto
|
||||
int hist_bins = 0; // 0 = Sturges
|
||||
float pie_radius = 0.0f; // 0 = default
|
||||
bool show_legend = true;
|
||||
bool show_markers = false; // line/area markers
|
||||
bool locked = false; // disable pan/zoom
|
||||
mutable bool fit_request = false; // consumed by viz::render
|
||||
};
|
||||
|
||||
// VizPanel: viz adicional sobre el mismo StageOutput.
|
||||
struct VizPanel {
|
||||
ViewMode display = ViewMode::Bar;
|
||||
ViewConfig config;
|
||||
mutable ViewMode last_non_table = ViewMode::Bar;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// State: stage pipeline + viz globales.
|
||||
// ----------------------------------------------------------------------------
|
||||
struct State {
|
||||
std::vector<Stage> stages;
|
||||
int active_stage = 0;
|
||||
ViewMode display = ViewMode::Table;
|
||||
ViewConfig viz_config;
|
||||
std::vector<VizPanel> extra_panels;
|
||||
std::vector<Join> joins; // aplicado antes de stages[0]
|
||||
std::string main_source; // name de TableInput; vacio -> tables[0]
|
||||
|
||||
std::vector<ColorRule> color_rules;
|
||||
std::vector<bool> col_visible;
|
||||
std::vector<int> col_order;
|
||||
|
||||
// Helpers (definidos en compute_stage.cpp).
|
||||
Stage& raw();
|
||||
const Stage& raw() const;
|
||||
Stage& active();
|
||||
const Stage& active_const() const;
|
||||
void ensure_stage0();
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Drill extendido (fase 10). Ver issue 0079.
|
||||
// ----------------------------------------------------------------------------
|
||||
enum class DateGranularity { None, Year, Month, Week, Day, Hour };
|
||||
|
||||
enum class FilterPreset { Last7d, Last30d, Last90d, ExcludeNulls, NonZero };
|
||||
|
||||
// Step de drill grabado para history undo/redo (fase 10).
|
||||
struct DrillStep {
|
||||
int target_stage = -1; // stage donde se anadio el filter
|
||||
int filter_pos = -1; // index en target_stage.filters
|
||||
int prev_active_stage = 0; // active_stage antes del drill
|
||||
Filter added; // filter para redo
|
||||
};
|
||||
|
||||
} // namespace data_table
|
||||
@@ -0,0 +1,96 @@
|
||||
#include "gfx/gpu_check.h"
|
||||
#include "gfx/gl_loader.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
// CUDA runtime version via compile-time macro.
|
||||
// cuda_runtime.h define CUDART_VERSION como XXYYZZ (ej. 12040 para 12.4.0).
|
||||
// Solo se incluye si el header esta disponible; si no, cuda_runtime_version = "".
|
||||
#if defined(__has_include) && __has_include(<cuda_runtime.h>)
|
||||
#include <cuda_runtime.h>
|
||||
#define FN_HAS_CUDA_RUNTIME 1
|
||||
#endif
|
||||
|
||||
namespace fn::gfx {
|
||||
|
||||
static std::string safe_gl_string(GLenum name) {
|
||||
const GLubyte* s = glGetString(name);
|
||||
if (!s) return "";
|
||||
return std::string(reinterpret_cast<const char*>(s));
|
||||
}
|
||||
|
||||
static bool check_gl_version_43() {
|
||||
// GL_VERSION tiene formato "major.minor ..." o "OpenGL ES major.minor ..."
|
||||
const GLubyte* ver = glGetString(GL_VERSION);
|
||||
if (!ver) return false;
|
||||
int major = 0, minor = 0;
|
||||
// Saltar prefijo "OpenGL ES " si lo hay
|
||||
const char* p = reinterpret_cast<const char*>(ver);
|
||||
if (std::strncmp(p, "OpenGL ES ", 10) == 0) p += 10;
|
||||
// sscanf con la forma "X.Y"
|
||||
// NOLINTNEXTLINE(cert-err34-c)
|
||||
std::sscanf(p, "%d.%d", &major, &minor);
|
||||
return (major > 4) || (major == 4 && minor >= 3);
|
||||
}
|
||||
|
||||
bool gpu_check_caps(GpuCaps& out) {
|
||||
out = GpuCaps{}; // reset
|
||||
|
||||
out.gl_vendor = safe_gl_string(GL_VENDOR);
|
||||
out.gl_renderer = safe_gl_string(GL_RENDERER);
|
||||
out.gl_version = safe_gl_string(GL_VERSION);
|
||||
|
||||
if (out.gl_vendor.empty()) {
|
||||
// No hay contexto GL activo.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute shader support: GL 4.3+ o ARB_compute_shader
|
||||
{
|
||||
const GLubyte* exts = glGetString(GL_EXTENSIONS);
|
||||
bool has_arb = exts &&
|
||||
std::strstr(reinterpret_cast<const char*>(exts),
|
||||
"GL_ARB_compute_shader") != nullptr;
|
||||
out.has_compute_shader = check_gl_version_43() || has_arb;
|
||||
}
|
||||
|
||||
// Shader storage buffer: GL 4.3+ o ARB_shader_storage_buffer_object
|
||||
{
|
||||
const GLubyte* exts = glGetString(GL_EXTENSIONS);
|
||||
bool has_ssbo_arb = exts &&
|
||||
std::strstr(reinterpret_cast<const char*>(exts),
|
||||
"GL_ARB_shader_storage_buffer_object") != nullptr;
|
||||
out.has_storage_buffer = check_gl_version_43() || has_ssbo_arb;
|
||||
}
|
||||
|
||||
// Workgroup limits (solo si hay compute shader support)
|
||||
if (out.has_compute_shader) {
|
||||
// GL_MAX_COMPUTE_WORK_GROUP_COUNT — indexed query
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 0, &out.max_compute_workgroup_count[0]);
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 1, &out.max_compute_workgroup_count[1]);
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_COUNT, 2, &out.max_compute_workgroup_count[2]);
|
||||
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 0, &out.max_compute_workgroup_size[0]);
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 1, &out.max_compute_workgroup_size[1]);
|
||||
glGetIntegeri_v(GL_MAX_COMPUTE_WORK_GROUP_SIZE, 2, &out.max_compute_workgroup_size[2]);
|
||||
}
|
||||
|
||||
// CUDA runtime version (compile-time detection)
|
||||
#if defined(FN_HAS_CUDA_RUNTIME)
|
||||
{
|
||||
int cuda_ver = CUDART_VERSION; // ej. 12040 para CUDA 12.4.0
|
||||
int major = cuda_ver / 1000;
|
||||
int minor = (cuda_ver % 1000) / 10;
|
||||
char buf[16];
|
||||
std::snprintf(buf, sizeof(buf), "%d.%d", major, minor);
|
||||
out.cuda_runtime_version = buf;
|
||||
}
|
||||
#else
|
||||
out.cuda_runtime_version = "";
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace fn::gfx
|
||||
@@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace fn::gfx {
|
||||
|
||||
// GpuCaps recopila capacidades OpenGL y CUDA del contexto activo.
|
||||
// Todos los campos de cadena estan vacios ("") si el dato no esta disponible.
|
||||
struct GpuCaps {
|
||||
// OpenGL — requieren contexto GL activo antes de llamar gpu_check_caps.
|
||||
std::string gl_vendor; // glGetString(GL_VENDOR) ej. "NVIDIA Corporation"
|
||||
std::string gl_renderer; // glGetString(GL_RENDERER) ej. "NVIDIA GeForce RTX 3080/PCIe/SSE2"
|
||||
std::string gl_version; // glGetString(GL_VERSION) ej. "4.6.0 NVIDIA 550.54.15"
|
||||
|
||||
// Compute shader limits (GL_MAX_COMPUTE_WORK_GROUP_COUNT/SIZE)
|
||||
// Indice 0=X 1=Y 2=Z. Valor 0 si compute shaders no disponibles.
|
||||
int max_compute_workgroup_count[3] = {0, 0, 0};
|
||||
int max_compute_workgroup_size[3] = {0, 0, 0};
|
||||
|
||||
bool has_compute_shader = false; // GL_VERSION >= 4.3 o extension ARB_compute_shader
|
||||
bool has_storage_buffer = false; // GL_VERSION >= 4.3 o extension ARB_shader_storage_buffer_object
|
||||
|
||||
// CUDA — vacio si CUDA runtime no detectado en compile time.
|
||||
// Formato: "12.4" (major.minor) o "" si no disponible.
|
||||
std::string cuda_runtime_version;
|
||||
};
|
||||
|
||||
// gpu_check_caps rellena out con las capacidades del contexto OpenGL activo.
|
||||
//
|
||||
// REQUISITO: debe llamarse despues de inicializar el contexto GL y, en Windows,
|
||||
// despues de fn::gfx::gl_loader_init(). Si se llama sin contexto activo el
|
||||
// comportamiento es indefinido (glGetString devuelve nullptr).
|
||||
//
|
||||
// Retorna true si se pudo leer al menos el vendor GL (contexto activo).
|
||||
// Retorna false si gl_vendor queda vacio (contexto no activo o driver defectuoso).
|
||||
bool gpu_check_caps(GpuCaps& out);
|
||||
|
||||
} // namespace fn::gfx
|
||||
@@ -0,0 +1,86 @@
|
||||
---
|
||||
name: gpu_check
|
||||
kind: function
|
||||
lang: cpp
|
||||
domain: gfx
|
||||
version: "1.0.0"
|
||||
purity: impure
|
||||
signature: "bool fn_gfx::gpu_check_caps(GpuCaps& out)"
|
||||
description: "Rellena GpuCaps con las capacidades del contexto OpenGL activo: vendor, renderer, version, limites de compute workgroup, flags has_compute_shader/has_storage_buffer, y version CUDA runtime (deteccion en compile-time via CUDART_VERSION). Requiere contexto GL activo. Retorna false si el contexto no esta disponible."
|
||||
tags: [gpu, opengl, cuda, caps, hardware, probe, gfx, compute, infra]
|
||||
uses_functions: ["gl_loader_cpp_gfx"]
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: "error_go_core"
|
||||
imports: [gfx/gpu_check.h, gfx/gl_loader.h, cuda_runtime.h, cstring, string]
|
||||
tested: false
|
||||
tests: []
|
||||
test_file_path: ""
|
||||
file_path: "cpp/functions/gfx/gpu_check.cpp"
|
||||
framework: opengl
|
||||
params:
|
||||
- name: out
|
||||
desc: "Referencia a GpuCaps que se rellena con las capacidades detectadas. Se resetea al inicio de la llamada."
|
||||
output: "true si el contexto GL esta activo y gl_vendor no esta vacio; false si no hay contexto GL activo o el driver devuelve nullptr para GL_VENDOR."
|
||||
---
|
||||
|
||||
# gpu_check
|
||||
|
||||
Probing de capacidades GPU en runtime: OpenGL strings, compute shader support y CUDA.
|
||||
|
||||
## Uso tipico
|
||||
|
||||
```cpp
|
||||
#include "gfx/gpu_check.h"
|
||||
#include "gfx/gl_loader.h"
|
||||
|
||||
// Dentro de render(), despues del primer frame (contexto GL activo):
|
||||
fn::gfx::GpuCaps caps;
|
||||
if (fn::gfx::gpu_check_caps(caps)) {
|
||||
printf("GPU: %s\n", caps.gl_renderer.c_str());
|
||||
printf("Compute shaders: %s\n", caps.has_compute_shader ? "yes" : "no");
|
||||
if (!caps.cuda_runtime_version.empty())
|
||||
printf("CUDA runtime: %s\n", caps.cuda_runtime_version.c_str());
|
||||
} else {
|
||||
printf("No GL context active\n");
|
||||
}
|
||||
```
|
||||
|
||||
## Estructura GpuCaps
|
||||
|
||||
```cpp
|
||||
struct GpuCaps {
|
||||
std::string gl_vendor; // "NVIDIA Corporation"
|
||||
std::string gl_renderer; // "NVIDIA GeForce RTX 3080/PCIe/SSE2"
|
||||
std::string gl_version; // "4.6.0 NVIDIA 550.54.15"
|
||||
int max_compute_workgroup_count[3]; // [65535, 65535, 65535] tipico NVIDIA
|
||||
int max_compute_workgroup_size[3]; // [1024, 1024, 64] tipico
|
||||
bool has_compute_shader; // GL 4.3+ o ARB_compute_shader
|
||||
bool has_storage_buffer; // GL 4.3+ o ARB_shader_storage_buffer_object
|
||||
std::string cuda_runtime_version; // "12.4" o "" si no compilado con CUDA
|
||||
};
|
||||
```
|
||||
|
||||
## CUDA detection
|
||||
|
||||
La version CUDA se detecta en **compile time** via el macro `CUDART_VERSION` de `<cuda_runtime.h>`. Si la app no esta compilada con el CUDA toolkit, `cuda_runtime_version` sera `""`. Para detection en runtime del toolkit del sistema, usar `cuda_toolkit_check_bash_infra`.
|
||||
|
||||
## Requisito de contexto GL
|
||||
|
||||
Llamar siempre despues de crear el contexto GL. En apps que usan `fn::run_app`, el contexto esta activo desde el primer frame del `render()` callback. En Windows, `fn::gfx::gl_loader_init()` debe haberse llamado antes para que los punteros de funcion esten resueltos.
|
||||
|
||||
## Uso previsto (fn doctor cpp-apps)
|
||||
|
||||
Esta funcion sera invocada por el audit de `fn doctor cpp-apps` para verificar que las apps C++ del registry tienen acceso a compute shaders cuando declaran dependencias de `gpu_compute_program`, `gpu_dispatch`, etc.
|
||||
|
||||
## CMakeLists.txt
|
||||
|
||||
```cmake
|
||||
add_imgui_app(mi_app
|
||||
main.cpp
|
||||
${CMAKE_SOURCE_DIR}/cpp/functions/gfx/gpu_check.cpp
|
||||
)
|
||||
# CUDA opcional: si la app compila con CUDA toolkit el header cuda_runtime.h
|
||||
# estara disponible y FN_HAS_CUDA_RUNTIME se activara automaticamente.
|
||||
```
|
||||
Reference in New Issue
Block a user