C 811 806 800 783 753 Bytes
#define S(y) SDL_##y;
#define s unsigned
#define u s char
#define _ g[i*256+j]
#define L for(s i=0;i<256;i++)for(s j=0;j<256;j++)
#include <SDL2/SDL.h>
struct __attribute__((__packed__)){u l:1;u n:7;}g[1<<16];main(u k, u** v){S(Window*w)S(Renderer*r)S(Texture*t)uint32_t p[1<<16];S(CreateWindowAndRenderer(256,256,0,&w,&r))t=S(CreateTexture(r,372645892,1,256,256))read(open(v[1],0),g,1<<16);for(;;){L _.n=g[((u)(i-1))*256+((u)(j-1))].l+g[((u)(i-1))*256+j].l+g[((u)(i-1))*256+(u)(j+1)].l+g[(i<<8)+(u)(j-1)].l+g[(i*256)+(u)(j+1)].l+g[((u)(i+1))*256+((u)(j-1))].l+g[((u)(i+1))*256+j].l+g[((u)(i+1))*256+(u)(j+1)].l;L _.l=(_.n==3||_.l&&_.n==2);for(s i=0;i<1<<16;i++){p[i]=(g[i].l<<7);}S(UpdateTexture(t,0,p,1024))S(RenderCopy(r,t,0,0))S(RenderPresent(r))}}
this one might be "overkill" for being 255x255 instead of just 20, but this way I didn't have to bound check and could just cast instead
To compile & run:
cc gol.c -lsdl2
./a.out /path/to/seed
To seed it:
Specify a file, the contents of the file will be read into the graph, and only the least-significant bit actually matters, I would recommend using /dev/urandom