Skip to content

Commit d6c2957

Browse files
authored
Implement environment bump mapping for GeForce (#731)
This change allows [BumpWaves](https://github.com/user-attachments/files/25371854/BumpWaves.zip) test to work correctly with 45.23 driver, NV20 and NV35. Additionally, this change fixes rendering of hardware accelerated cube from DxDiag 4.08 with 45.23 driver and NV35. <img width="650" height="564" alt="Screenshot_2026-02-17_20-02-06" src="https://github.com/user-attachments/assets/861e4fc7-a765-4ead-ab6e-e31cfcdd6b92" />
1 parent d8dd793 commit d6c2957

File tree

2 files changed

+79
-30
lines changed

2 files changed

+79
-30
lines changed

bochs/iodev/display/geforce.cc

Lines changed: 75 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4067,22 +4067,8 @@ float rc_get_var(Bit32u cw, Bit32u shift, float regs[16][4], Bit32u civ)
40674067
}
40684068
}
40694069

4070-
void bx_geforce_c::d3d_register_combiners(gf_channel* ch, float ps_in[16][4], float out[4])
4071-
{
4072-
float regs[16][4];
4073-
for (Bit32u ci = 0; ci < 4; ci++) {
4074-
regs[0][ci] = 0.0f;
4075-
regs[3][ci] = 1.0f;
4076-
regs[4][ci] = ps_in[1][ci];
4077-
regs[5][ci] = ps_in[2][ci];
4078-
}
4079-
regs[0xe][3] = 0.0f;
4080-
regs[0xf][3] = 0.0f;
4081-
for (Bit32u t = 0; t < ch->d3d_tex_coord_count; t++) {
4082-
gf_texture* tex = &ch->d3d_texture[t];
4083-
if (tex->enabled)
4084-
d3d_sample_texture(ch, tex, ps_in[4 + t], regs[8 + t]);
4085-
}
4070+
void bx_geforce_c::d3d_register_combiners(gf_channel* ch, float regs[16][4], float out[4])
4071+
{
40864072
for (Bit32u s = 0; s < ch->d3d_combiner_control_num_stages; s++) {
40874073
Bit32u icws[2] = {
40884074
ch->d3d_combiner_color_icw[s],
@@ -4310,20 +4296,14 @@ void bx_geforce_c::d3d_pixel_shader(gf_channel* ch,
43104296
for (int comp_index = 0; comp_index < 4; comp_index++)
43114297
op_result[comp_index] = floor(params[0][comp_index]);
43124298
break;
4313-
case 0x17: { // TEX
4314-
Bit32u tex_unit = (dst_word >> 17) & 0xf;
4315-
gf_texture* tex = &ch->d3d_texture[tex_unit];
4316-
d3d_sample_texture(ch, tex, params[0], op_result);
4317-
if (((dst_word >> 21) & 1) != 0)
4318-
for (int comp_index = 0; comp_index < 4; comp_index++)
4319-
op_result[comp_index] = op_result[comp_index] * 2.0f - 1.0f;
4320-
break;
4321-
}
43224299
case 0x18: { // TXP
43234300
float winv = 1.0f / params[0][3];
43244301
params[0][0] *= winv;
43254302
params[0][1] *= winv;
43264303
params[0][2] *= winv;
4304+
// fallthrough
4305+
}
4306+
case 0x17: { // TEX
43274307
Bit32u tex_unit = (dst_word >> 17) & 0xf;
43284308
gf_texture* tex = &ch->d3d_texture[tex_unit];
43294309
d3d_sample_texture(ch, tex, params[0], op_result);
@@ -4376,6 +4356,10 @@ void bx_geforce_c::d3d_pixel_shader(gf_channel* ch,
43764356
op_result[comp_index] = dp2a;
43774357
break;
43784358
}
4359+
case 0x34: // TXPBEM
4360+
params[0][0] /= params[0][3];
4361+
params[0][1] /= params[0][3];
4362+
// fallthrough
43794363
case 0x33: { // TEXBEM
43804364
float coords[3];
43814365
coords[0] = params[0][0] + params[1][0] * params[2][0] + params[1][1] * params[2][1];
@@ -5009,13 +4993,65 @@ void bx_geforce_c::d3d_triangle_clipped(gf_channel* ch, float v0[16][4], float v
50094993
float tmp_regs32[64][4];
50104994
for (int comp_index = 0; comp_index < 4; comp_index++)
50114995
tmp_regs16[0][comp_index] = ps_in[1][comp_index];
5012-
if (ch->d3d_combiner_control_num_stages != 0) {
5013-
d3d_register_combiners(ch, ps_in, tmp_regs16[0]);
5014-
} else if (ch->d3d_shader_obj != 0) {
4996+
bool ps_enable = ch->d3d_shader_obj != 0;
4997+
bool rc_enable = ch->d3d_combiner_control_num_stages != 0;
4998+
float rc_regs[16][4];
4999+
if (ps_enable) {
50155000
ps_in[0][0] = xy[0] - ch->d3d_window_offset_x;
50165001
ps_in[0][1] = ch->d3d_viewport_height - (xy[1] - ch->d3d_window_offset_y);
50175002
ps_in[0][2] = 0.0f;
5018-
d3d_pixel_shader(ch, ps_in, tmp_regs16, tmp_regs32);
5003+
if (rc_enable)
5004+
d3d_pixel_shader(ch, ps_in, &rc_regs[8], tmp_regs32);
5005+
else
5006+
d3d_pixel_shader(ch, ps_in, tmp_regs16, tmp_regs32);
5007+
}
5008+
if (rc_enable) {
5009+
for (Bit32u ci = 0; ci < 4; ci++) {
5010+
rc_regs[0][ci] = 0.0f;
5011+
rc_regs[3][ci] = 1.0f;
5012+
rc_regs[4][ci] = ps_in[1][ci];
5013+
rc_regs[5][ci] = ps_in[2][ci];
5014+
}
5015+
rc_regs[0xe][3] = 0.0f;
5016+
rc_regs[0xf][3] = 0.0f;
5017+
if (!ps_enable) {
5018+
for (Bit32u t = 0; t < ch->d3d_tex_coord_count; t++) {
5019+
switch (ch->d3d_tex_shader_op[t]) {
5020+
case 0x00: // NONE
5021+
break;
5022+
case 0x01: // PROJECT2D
5023+
case 0x03: { // CUBEMAP
5024+
gf_texture* tex = &ch->d3d_texture[t];
5025+
d3d_sample_texture(ch, tex, ps_in[4 + t], rc_regs[8 + t]);
5026+
break;
5027+
}
5028+
case 0x06: { // BUMPENVMAP
5029+
float* in_coords = ps_in[4 + t];
5030+
float* prev_color = rc_regs[8 + ch->d3d_tex_shader_previous[t]];
5031+
float coords[3];
5032+
gf_texture* tex = &ch->d3d_texture[t];
5033+
coords[0] = in_coords[0] / in_coords[3] +
5034+
tex->offset_matrix[0] * prev_color[2] +
5035+
tex->offset_matrix[3] * prev_color[1];
5036+
coords[1] = in_coords[1] / in_coords[3] +
5037+
tex->offset_matrix[1] * prev_color[2] +
5038+
tex->offset_matrix[2] * prev_color[1];
5039+
coords[2] = 0.0f;
5040+
d3d_sample_texture(ch, tex, coords, rc_regs[8 + t]);
5041+
break;
5042+
}
5043+
default: { // not implemented
5044+
float* color = rc_regs[8 + t];
5045+
color[0] = 0.0f;
5046+
color[1] = 0.5f;
5047+
color[2] = 0.5f;
5048+
color[3] = 1.0f;
5049+
break;
5050+
}
5051+
}
5052+
}
5053+
}
5054+
d3d_register_combiners(ch, rc_regs, tmp_regs16[0]);
50195055
}
50205056
float a = BX_MIN(BX_MAX(tmp_regs16[0][3], 0.0f), 1.0f);
50215057
if (ch->d3d_alpha_test_enable) {
@@ -6529,6 +6565,8 @@ void bx_geforce_c::execute_d3d(gf_channel* ch, Bit32u cls, Bit32u method, Bit32u
65296565
tex->enabled = param >> 31;
65306566
else
65316567
tex->enabled = (param >> 30) & 1;
6568+
if (cls == 0x0096)
6569+
ch->d3d_tex_shader_op[texture_index] = tex->enabled ? 0x01 : 0x00;
65326570
} else if ((texture_method == 3 && cls == 0x0096) ||
65336571
(texture_method == 4 && cls != 0x0096)) {
65346572
tex->control1 = param;
@@ -6552,6 +6590,8 @@ void bx_geforce_c::execute_d3d(gf_channel* ch, Bit32u cls, Bit32u method, Bit32u
65526590
(texture_method == 8 && cls == 0x0097)) {
65536591
tex->pal_dma_obj = (param & 1) == 1 ? ch->d3d_b_obj : ch->d3d_a_obj;
65546592
tex->pal_ofs = param & 0xffffffc0;
6593+
} else if (texture_method >= 10 && texture_method <= 13 && cls == 0x0097) {
6594+
tex->offset_matrix[texture_method - 10] = u.param_float;
65556595
}
65566596
} else if (method == 0x75b)
65576597
ch->d3d_semaphore_offset = param;
@@ -6576,6 +6616,12 @@ void bx_geforce_c::execute_d3d(gf_channel* ch, Bit32u cls, Bit32u method, Bit32u
65766616
(method == 0x23f && cls == 0x0497)) {
65776617
ch->d3d_combiner_control = param;
65786618
ch->d3d_combiner_control_num_stages = param & 0xf;
6619+
} else if (method == 0x79c && cls == 0x0097) {
6620+
for (Bit32u i = 0; i < 4; i++)
6621+
ch->d3d_tex_shader_op[i] = (param >> (i * 5)) & 0x1f;
6622+
} else if (method == 0x79e && cls == 0x0097) {
6623+
ch->d3d_tex_shader_previous[2] = (param >> 16) & 3;
6624+
ch->d3d_tex_shader_previous[3] = (param >> 20) & 3;
65796625
} else if (method == 0x7a5) {
65806626
ch->d3d_transform_execution_mode = param;
65816627
} else if (method == 0x7a7) {

bochs/iodev/display/geforce.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct gf_texture
6969
Bit32u pal_ofs;
7070
Bit32u control3;
7171
Bit32u key_color;
72+
float offset_matrix[4];
7273
};
7374

7475
struct gf_channel
@@ -317,6 +318,8 @@ struct gf_channel
317318
Bit32u d3d_combiner_color_ocw[8];
318319
Bit32u d3d_combiner_control;
319320
Bit32u d3d_combiner_control_num_stages;
321+
Bit32u d3d_tex_shader_op[4];
322+
Bit32u d3d_tex_shader_previous[4];
320323
Bit32u d3d_transform_execution_mode;
321324
Bit32u d3d_transform_program_load;
322325
Bit32u d3d_transform_program_start;
@@ -531,7 +534,7 @@ class bx_geforce_c : public bx_vgacore_c
531534
BX_GEFORCE_SMF void d3d_sample_texture(gf_channel* ch,
532535
gf_texture* tex, float coords_in[3], float color[4]);
533536
BX_GEFORCE_SMF void d3d_vertex_shader(gf_channel* ch, float in[16][4], float out[16][4]);
534-
BX_GEFORCE_SMF void d3d_register_combiners(gf_channel* ch, float ps_in[16][4], float out[4]);
537+
BX_GEFORCE_SMF void d3d_register_combiners(gf_channel* ch, float regs[16][4], float out[4]);
535538
BX_GEFORCE_SMF void d3d_pixel_shader(gf_channel* ch, float in[16][4], float tmp_regs16[64][4], float tmp_regs32[64][4]);
536539
BX_GEFORCE_SMF void d3d_normal_to_view(gf_channel* ch, float n[3], float nt[3]);
537540
BX_GEFORCE_SMF void d3d_triangle(gf_channel* ch, Bit32u base);

0 commit comments

Comments
 (0)