diff options
| author | Alejandro Soto <alejandro@34project.org> | 2023-11-12 01:37:02 -0600 |
|---|---|---|
| committer | Alejandro Soto <alejandro@34project.org> | 2023-11-14 07:18:16 -0600 |
| commit | bf6b4e2e8ebb63f6b8466bc98650ce75f3bdc79f (patch) | |
| tree | d3fbcb5b8582fce317fdae71e4b32c9398266a6a /rtl/gfx | |
| parent | 50440e25024b5d64b36396d2a5f5b8413d93eefc (diff) | |
rtl/gfx: implement fragment shading
Diffstat (limited to 'rtl/gfx')
| -rw-r--r-- | rtl/gfx/gfx_defs.sv | 13 | ||||
| -rw-r--r-- | rtl/gfx/gfx_frag.sv | 30 | ||||
| -rw-r--r-- | rtl/gfx/gfx_frag_addr.sv | 2 | ||||
| -rw-r--r-- | rtl/gfx/gfx_frag_shade.sv | 53 | ||||
| -rw-r--r-- | rtl/gfx/gfx_lerp.sv | 32 |
5 files changed, 123 insertions, 7 deletions
diff --git a/rtl/gfx/gfx_defs.sv b/rtl/gfx/gfx_defs.sv index cc6e6f3..429928c 100644 --- a/rtl/gfx/gfx_defs.sv +++ b/rtl/gfx/gfx_defs.sv @@ -38,9 +38,13 @@ typedef logic[19:0] half_coord; `define GFX_Y_RES 480 `define GFX_LINEAR_RES (`GFX_X_RES * `GFX_Y_RES) +`define COLOR_CHANNELS 4 + +typedef logic[7:0] color8; + typedef struct packed { - logic[7:0] r, g, b; + color8 r, g, b; } rgb24; typedef struct packed @@ -50,13 +54,14 @@ typedef struct packed typedef struct packed { - logic[7:0] a, r, g, b; + color8 a, r, g, b; } rgb32; `define FIXED_FRAC 16 `define FIXED_FMA_STAGES 5 `define FIXED_FMA_DOT_STAGES (2 * `FIXED_FMA_STAGES) +`define LERP_STAGES `FIXED_FMA_DOT_STAGES typedef logic signed[31:0] fixed; typedef fixed[2:0] fixed_tri; @@ -119,6 +124,7 @@ typedef struct packed typedef frag_xy[`GFX_FINE_LANES - 1:0] frag_xy_lanes; typedef logic[`GFX_FINE_LANES - 1:0] paint_lanes; +typedef fixed[`COLOR_CHANNELS - 1:0] color_lerp_lanes; typedef struct packed { @@ -126,6 +132,7 @@ typedef struct packed rgb32 color; } frag_paint; -`define GFX_FRAG_ADDR_STAGES 3 +`define GFX_FRAG_ADDR_STAGES 3 +`define GFX_FRAG_SHADE_STAGES (`LERP_STAGES + 1) `endif diff --git a/rtl/gfx/gfx_frag.sv b/rtl/gfx/gfx_frag.sv index 3598ed9..b4481ce 100644 --- a/rtl/gfx/gfx_frag.sv +++ b/rtl/gfx/gfx_frag.sv @@ -27,7 +27,7 @@ module gfx_frag logic addr_ready, addr_stall; - gfx_pipeline_flow #(.STAGES(`GFX_FRAG_ADDR_STAGES)) addr_flow + gfx_pipeline_flow #(.STAGES(`GFX_FRAG_SHADE_STAGES)) addr_flow ( .stall(addr_stall), .in_ready(addr_ready), @@ -37,12 +37,36 @@ module gfx_frag .* ); + linear_coord linear; + gfx_frag_addr addr ( + .frag(funnel_frag), .stall(addr_stall), + .* + ); - .frag(funnel_frag), - .linear(), + localparam ADDR_WAIT_Z_STAGES = `GFX_FRAG_SHADE_STAGES - `GFX_FRAG_ADDR_STAGES; + + gfx_pipes #(.WIDTH($bits(linear_coord)), .DEPTH(ADDR_WAIT_Z_STAGES)) addr_pipes + ( + .in(linear), + .out(), + .stall(addr_stall), + .* + ); + + gfx_frag_shade shade + ( + .stall(addr_stall), + + .b1(), + .b2(), + .color(), + + .argb0(), + .argb1_argb0(), + .argb2_argb0(), .* ); diff --git a/rtl/gfx/gfx_frag_addr.sv b/rtl/gfx/gfx_frag_addr.sv index 9b817cb..23bd315 100644 --- a/rtl/gfx/gfx_frag_addr.sv +++ b/rtl/gfx/gfx_frag_addr.sv @@ -17,7 +17,7 @@ module gfx_frag_addr * * linear = y_corregido * `GFX_X_RES + x_corregido * - * Afortunadamente, esto es trivializable y no necesita FMA: + * Afortunadamente, esto no necesita una FMA, como procederé a demostrar: * * y * `GFX_X_RES + x * = y * 640 + x diff --git a/rtl/gfx/gfx_frag_shade.sv b/rtl/gfx/gfx_frag_shade.sv new file mode 100644 index 0000000..d2ad7ce --- /dev/null +++ b/rtl/gfx/gfx_frag_shade.sv @@ -0,0 +1,53 @@ +`include "gfx/gfx_defs.sv" + +module gfx_frag_shade +( + input logic clk, + + input fixed b1, + b2, + input color_lerp_lanes argb0, + argb1_argb0, + argb2_argb0, + input logic stall, + + output rgb32 color +); + + struct packed + { + logic sign; + logic[$bits(fixed) - `FIXED_FRAC - 2:0] out_of_range; + color8 color; + logic[`FIXED_FRAC - $bits(color8) - 1:0] sub; + } lerped[`COLOR_CHANNELS]; + + fixed channel_lerp[`COLOR_CHANNELS]; + color8[`COLOR_CHANNELS - 1:0] out; + + assign color = out; + + genvar i; + generate + for (i = 0; i < `COLOR_CHANNELS; ++i) begin: channels + assign lerped[i] = channel_lerp[i]; + + gfx_lerp lerp + ( + .q(channel_lerp[i]), + .q0(argb0[i]), + .q1_q0(argb1_argb0[i]), + .q2_q0(argb2_argb0[i]), + .* + ); + + always_ff @(posedge clk) + if (!stall) begin + out[i] <= lerped[i].color; + if (lerped[i].sign || |lerped[i].out_of_range) + out[i] <= {($bits(color8)){!lerped[i].sign}}; + end + end + endgenerate + +endmodule diff --git a/rtl/gfx/gfx_lerp.sv b/rtl/gfx/gfx_lerp.sv new file mode 100644 index 0000000..42e4393 --- /dev/null +++ b/rtl/gfx/gfx_lerp.sv @@ -0,0 +1,32 @@ +`include "gfx/gfx_defs.sv" + +module gfx_lerp +( + input logic clk, + + input fixed b1, + b2, + q0, + q1_q0, + q2_q0, + input logic stall, + + output fixed q +); + + /* Interpolación lineal, trivializada. + * + * Esta es la clave: https://fgiesen.wordpress.com/2013/02/06/the-barycentric-conspirac/ + */ + + gfx_fixed_fma_dot fma + ( + .c(q0), + .a0(b1), + .b0(q1_q0), + .a1(b2), + .b1(q2_q0), + .* + ); + +endmodule |
