No sé para qué me gasto el dinero, pero me alegro de que Nvidia esté “liberando” los gpu gems.
No están todos, cada semana tres capítulos nuevos, así nadie se atraganta
Relacionadas: gpu gems online
No sé para qué me gasto el dinero, pero me alegro de que Nvidia esté “liberando” los gpu gems.
No están todos, cada semana tres capítulos nuevos, así nadie se atraganta
Relacionadas: gpu gems online
Haciendo honor al nombre del blog, y aprovechando que recientemente me han comentado que el API de lua es un poco rara, vamos a hincarle el diente directamente al problema. Este post es sólo para programadores, no trata del léxico/sintaxis de lua, sólo de una parte muy particular del API, concretamente, la que más problema da al programador que se está iniciando en esto de lua.
Veamos en primer lugar que es eso de un lua_State*, es fácil crearlo (luaL_newstate), y destruirlo (lua_close) y representa un estado completo de lua. A efectos prácticos es como si con cada lua_State fuera una máquina virtual independiente, por lo que podemos tener tantos como queramos (uno por thread, uno por efecto, uno por agente, etc, etc…).

Las Breakpoint’s siempre dejan demos espectaculares pero, personalmente, lo que más me fascina de la party son la calidad de algunos de sus seminarios. Se molestan en organizarlos, grabarlos y dejarlos online para disfrute de todo el mundo.
A mi me han gustado especialmente, sin ningún orden específico:
(más…)
Conversación entre ingenieros, uno puramente de gráficos ( o eso dice ), orgulloso tras cazar un bug:
- oh si
- arreglaooo
- qué era?
- pues que se liberaba un shader cuando ya no habia contexto de render pq no se hacia un “clear” de los stateBlocks en el destroy de State
- pues que el motor de fluzo generaba una compresión espacio-temporal en la indeterminación producida por los hadrones
- vale vale, me lo creo
- XDDDD
- en nvidia el driver debe decir… “paso de ti…”
- en ati dice..” diosssssss que haceeees!!!??”
- ya te digo, lo mismito que espeta el inyector de fluzo en el cableado de interconexión cutáneo… mira que están mal diseñados esos drivers
- basicamente , glDeleteShader(id) cuando contexto de render no existir, poder pasar dos cosas:
- si nvidia, no pasar nada
- si ati, driver cagarse en tu p%&$·@ madre
- XDDD
- ah vale, ahora sí
- xDDDDDD
Maravillas de ATI vs Nvidia
Existe por ahí un script llamado woof usado principalmente para mandar ficheros de una forma sencilla, está escrito en python y bueno, no es que tenga una cruzada contra python, pero tampoco creo que tengamos que hacerlo ahora todo en python por muy de moda que esté. Concretamente woof no va bien en cygwin (o eso dicen), o bueno igual quieres usarlo desde tu fonera hackeada y no quieres/necesitas python… yo que sé, el caso es que hay formas más fáciles de mandar ficheros a-lo-servidor-web. Yo os propongo una que sólo hace uso de netcat (que siempre puedes usar a mano netcateando).
Se llama ncweb (de netcat-web) es muy simplón, no tiene opciones y ocupa más el comentario de la licencia que el propio fichero. La parte graciosa es cómo mandar algo con formato web, es decir cómo nos manda un servidor web un fichero:
# Execute netcat with http header
(
echo -e "HTTP/1.1 200 OK\r"
echo -e "Connection: close\r"
echo -e "Content-Length: $LENGTH\r"
echo -e "Content-Type: $TYPE\r"
echo -e "\r"
cat $1
echo -e "\r"
) | nc -q 1 -l -p $PORT
Para ver cómo se calcula y que son $LENGH, $TYPE, y $PORT mirad el código, el $1 es el argumento que nos pasan al script y poco más hay que decir. Con esto ya tienes para mandar ficheros por red de forma sencilla y rápida.
Por cierto, va bastante más rápido que woof… ![]()
Vamos a darle un giro de tuerca a lo que vimos en el post anterior, en este post veremos cómo compilar con cmake usando vim de forma productiva. En primer lugar, necesitamos algo que nos permita compilar un proyecto (de cmake) cuando estamos editando sus ficheros. Mientras editamos los ficheros solemos estar dentro de algún subdirectorio del proyecto con lo que nos bastaría un script que buscara el directorio build y el CMakeLists.txt y lanzara el make.
Es fácil escribir ese script, el mío lo llamo vim-cmake-makeprg y lo tengo accesible en ~/bin . Al ejecutarlo irá subiendo directorios hasta encontrar un CMakeLists.txt y un directorio build. El resultado es que cuando estoy dentro de un proyecto con este comando puedo compilarlo independientemente de donde esté.
Una vez tenemos el script, sólo nos queda decirle a vim que lo utilice para compilar, para ello editamos el ~/.vimrc y añadimos:
set makeprg=vim-cmake-makeprg
Ahora ya podemos trabajar en nuestro proyecto, editamos (con vim) cualquier fichero, empezamos a programar, y para compilar escribiremos:
:make

Aquí es donde comienza la magia de quickfix, en primero se pone a compilar, veremos la salida del proceso de compilación en el buffer de texto de vim. La salida se pasa por un filtro que va capturando los mensajes de error relevantes y los va añadiendo en una lista. Al terminar de compilar vim abrirá el primer fichero que contenga errores y posicionará el cursor en el primer error, también nos mostrará una versión resumida del error:

Podemos ver la lista completa de errores con el comando cl:

Finalmente, estos son algunos de los comandos que podemos usar con quickfix:
Usando vim+quickfix, y cmake tendremos definitivamente una forma mucho más eficiente de programar-compilar-corregir-programar…
Pequeño truco para mejorar nuestra productividad con cmake. La primera recomendación es crear siempre un directorio build dentro de nuestro proyecto. Este directorio no se subiría a ningún repositorio, lo usamos sólo para tener todos los binarios compilados, librerías, etc… separado siempre de nuestro código y cabeceras.
En un escenario típico se entra en el directorio build, se ejecuta “cmake ..”, después make, después bin/nuestro_programa… una y otra y otra vez. Esto lo haremos en una terminal sólo para compilar+ejecutar, en otra terminal o donde sea, tendremos el código que iremos desarrollando. A mi me tiene pasado que no distingo la terminal donde tengo el building del resto, incluso he llegado a cargarme cosas sin querer por culpa de esto. Para evitarlo me he escrito un fichero de aliases de bash que activo cuando estoy en mi directorio de build. El fichero lo podéis descargar de aquí y tiene esta pinta:
se activa escribiendo en el directorio de build:
. cmake-aliases
El punto(.) es importante, indica al shell actual que vamos a incorporar las definiciones de ese fichero. Nota, ese fichero tiene que estar accesible desde el path, o bien os toca poner la ruta completa donde lo tengáis.
Cosas que tiene definidas:
Espero que a alguno le sirva, como me sirve a mi ![]()
Como todo programador de C++ sabe, no existe función alguna para comprobar en tiempo de compilación si una clase A hereda de otra B. En tiempo de ejecución podemos usar dynamic_cast, pero con mucho cuidado:
Escribiendo plantillas nos podemos encontrar que necesitamos saber si una clase hereda de otra, por ejemplo, para especializar la plantilla con un código optimizado. En esta circunstancia sólo nos sirve de verdad si somos capaces de tomar la decisión en tiempo de compilación, y dado que C++ no ofrece nada para ello Alexandrescu nos revela este truco.
Cuando los tipos A y B son clases estamos hablando de si la clase A hereda de B, pero el truco funciona igual de bien para cualquier par tipos, por ejemplo, para saber si un int se puede convertir a float o mejor si una clase A tiene conversión definida a otra B (explicit conversion).
La respuesta es ¡sí!, y todo se lo debemos curiosamente a sizeof.
sizeof es realmente potente, se puede aplicar a cualquier expresión, sin importar lo compleja que esta sea, sizeof devolverá el tamaño de esta sin llegar a evaluar la expresión en tiempo de compilación. Esto significa que sizeof tiene presente la sobrecarga, la especialización de plantillas, reglas de conversión … absolutamente todo lo que pueda aparecer en una expresión de C++ . En realidad, sizeof es capaz de deducir el tipo de una expresión; desechando la expresión pero devolviendo su tamaño.Alexandrescu
Evaluar el valor de una expresión implica hacerlo en tiempo de ejecución, pero evaluar el tamaño del tipo devuelto por una expresión es algo que se debe realizar en tiempo de compilación. Lo que Alexandrescu nos viene a decir es que sizeof es precisamente capaz de esto, y al hacerlo desecha el valor de la expresión y “calcula” solamente el tamaño del tipo devuelto.
El truco consiste en tener un par de funciones de test sobrecargadas, una que acepta el tipo objetivo (B) y otra que acepte cualquier otra cosa. Cada función devuelve un tipo de tamaño diferente, al intentar llamar a la función test con el tipo A si existe la conversión de A a B se utilizará una función y si no, la otra. Tranquilos que los detalles siguen a continuación.
Primero creamos dos clases de tamaños diferentes, Alexandrescu nos recomienda algo como:
// Esta, por definición, ocupa 1 byte
typedef char S_True;
// Esta no se sabe cuanto ocupa, pero seguro que > 1
class S_False { char dummy[2]; }
Ahora necesitamos un par de funciones sobrecargadas, una que acepte B y devuelva S_True:
S_True Test(B);
Y otra para “todo lo demás”, y que tenga menos prioridad. De esta forma si el objeto de tipo A no se puede convertir de ningúna forma a B se utilice esta función. Para ello utilizamos la construcción de varargs que por definición siempre será el último recurso a utilizar.
S_False Test(...);
Ahora ya podemos averiguar si el tipo A se puede transformar en B, sin más que comparar el tamaño de evaluar la llamada de Test:
const bool existe_conversion = sizeof( Test(A()) ) == sizeof(S_True) ;
Y ya está!! ya tenemos una constante booleana que nos indica si la conversión es posible en tiempo de compilación… pero ¿cómo funciona? Recordemos lo que hemos venido comentando:
sizeof sólo evalúa el tamaño de una expresión sin necesidad de realizar llamadas reales, esto permite que no haga falta implementar nada en absoluto, nunca se van a llamar a ninguna función Test, ni al constructor de A(), ni nada… sizeof evalúa la expresión para ver qué tamaño tendrá el tipo del resultado.
Un pequeño problema es que la expresión “A()” tiene que ser válida lo que supone que el constructor por defecto debe existir en el tipo A. Como esto no tiene por qué ser cierto, vamos a darle un pequeño giro de tuerca.
A CrearInstancia();
const bool existe_conversion = sizeof( Test(CrearInstancia()) ) == sizeof(S_True) ;
La función CrearInstancia no hay que implementarla, nuevamente sizeof sólo la usa para saber que el parámetro de vuelvo es de tipo A, de esta forma evitamos tener que usar el constructor de A.
Con todo esto, ya tenemos para hacernos un template que nos diga si una clase es convertible a otra.
template <class A, class B>
class Conversion
{
typedef char S_True;
class S_False { char dummy[2]; }
static A CrearInstancia();
static S_True Test(B);
static S_False Test(…);
public:
enum {
existe = ( sizeof(Test(CrearInstancia())) == sizeof(S_True) )
};
};
Como ejemplo…
#include <iostream>
#include <vector>
int main() {
std::cout
<< Conversion<double,int>::existe << ' '
<< Conversion<char, char*>::existe << ' '
<< Conversion<size_t ,vector<int> >::existe << ' '
}
Y el resultado ‘1 0 0′ … Finalmente para detectar la herencia de clases (como decíamos en el tíutlo del post) lo que debemos es usar punteros constantes a los tipos:
Conversion<const clase1*, const clase2*>::existe
¡¡¡ Todo esto gracias a Alexandrescu y al power of sizeof !!!
Gestionado con WordPress