diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/vertex_shader.cpp | 75 |
1 files changed, 52 insertions, 23 deletions
diff --git a/src/video_core/vertex_shader.cpp b/src/video_core/vertex_shader.cpp index ff825e2e1..0c4827507 100644 --- a/src/video_core/vertex_shader.cpp +++ b/src/video_core/vertex_shader.cpp | |||
| @@ -349,12 +349,44 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 349 | break; | 349 | break; |
| 350 | } | 350 | } |
| 351 | default: | 351 | default: |
| 352 | { | ||
| 353 | static auto evaluate_condition = [](const VertexShaderState& state, bool refx, bool refy, Instruction::FlowControlType flow_control) { | ||
| 354 | bool results[2] = { refx == state.conditional_code[0], | ||
| 355 | refy == state.conditional_code[1] }; | ||
| 356 | |||
| 357 | switch (flow_control.op) { | ||
| 358 | case flow_control.Or: | ||
| 359 | return results[0] || results[1]; | ||
| 360 | |||
| 361 | case flow_control.And: | ||
| 362 | return results[0] && results[1]; | ||
| 363 | |||
| 364 | case flow_control.JustX: | ||
| 365 | return results[0]; | ||
| 366 | |||
| 367 | case flow_control.JustY: | ||
| 368 | return results[1]; | ||
| 369 | } | ||
| 370 | }; | ||
| 371 | |||
| 352 | // Handle each instruction on its own | 372 | // Handle each instruction on its own |
| 353 | switch (instr.opcode) { | 373 | switch (instr.opcode) { |
| 354 | case Instruction::OpCode::END: | 374 | case Instruction::OpCode::END: |
| 355 | exit_loop = true; | 375 | exit_loop = true; |
| 356 | break; | 376 | break; |
| 357 | 377 | ||
| 378 | case Instruction::OpCode::JMPC: | ||
| 379 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { | ||
| 380 | state.program_counter = &shader_memory[instr.flow_control.dest_offset] - 1; | ||
| 381 | } | ||
| 382 | break; | ||
| 383 | |||
| 384 | case Instruction::OpCode::JMPU: | ||
| 385 | if (shader_uniforms.b[instr.flow_control.bool_uniform_id]) { | ||
| 386 | state.program_counter = &shader_memory[instr.flow_control.dest_offset] - 1; | ||
| 387 | } | ||
| 388 | break; | ||
| 389 | |||
| 358 | case Instruction::OpCode::CALL: | 390 | case Instruction::OpCode::CALL: |
| 359 | call(state, | 391 | call(state, |
| 360 | instr.flow_control.dest_offset, | 392 | instr.flow_control.dest_offset, |
| @@ -362,6 +394,24 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 362 | binary_offset + 1); | 394 | binary_offset + 1); |
| 363 | break; | 395 | break; |
| 364 | 396 | ||
| 397 | case Instruction::OpCode::CALLU: | ||
| 398 | if (shader_uniforms.b[instr.flow_control.bool_uniform_id]) { | ||
| 399 | call(state, | ||
| 400 | instr.flow_control.dest_offset, | ||
| 401 | instr.flow_control.num_instructions, | ||
| 402 | binary_offset + 1); | ||
| 403 | } | ||
| 404 | break; | ||
| 405 | |||
| 406 | case Instruction::OpCode::CALLC: | ||
| 407 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { | ||
| 408 | call(state, | ||
| 409 | instr.flow_control.dest_offset, | ||
| 410 | instr.flow_control.num_instructions, | ||
| 411 | binary_offset + 1); | ||
| 412 | } | ||
| 413 | break; | ||
| 414 | |||
| 365 | case Instruction::OpCode::NOP: | 415 | case Instruction::OpCode::NOP: |
| 366 | break; | 416 | break; |
| 367 | 417 | ||
| @@ -384,29 +434,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 384 | { | 434 | { |
| 385 | // TODO: Do we need to consider swizzlers here? | 435 | // TODO: Do we need to consider swizzlers here? |
| 386 | 436 | ||
| 387 | auto flow_control = instr.flow_control; | 437 | if (evaluate_condition(state, instr.flow_control.refx, instr.flow_control.refy, instr.flow_control)) { |
| 388 | bool results[3] = { (bool)flow_control.refx == state.conditional_code[0], | ||
| 389 | (bool)flow_control.refy == state.conditional_code[1] }; | ||
| 390 | |||
| 391 | switch (flow_control.op) { | ||
| 392 | case flow_control.Or: | ||
| 393 | results[2] = results[0] || results[1]; | ||
| 394 | break; | ||
| 395 | |||
| 396 | case flow_control.And: | ||
| 397 | results[2] = results[0] && results[1]; | ||
| 398 | break; | ||
| 399 | |||
| 400 | case flow_control.JustX: | ||
| 401 | results[2] = results[0]; | ||
| 402 | break; | ||
| 403 | |||
| 404 | case flow_control.JustY: | ||
| 405 | results[2] = results[1]; | ||
| 406 | break; | ||
| 407 | } | ||
| 408 | |||
| 409 | if (results[2]) { | ||
| 410 | call(state, | 438 | call(state, |
| 411 | binary_offset + 1, | 439 | binary_offset + 1, |
| 412 | instr.flow_control.dest_offset - binary_offset - 1, | 440 | instr.flow_control.dest_offset - binary_offset - 1, |
| @@ -429,6 +457,7 @@ static void ProcessShaderCode(VertexShaderState& state) { | |||
| 429 | 457 | ||
| 430 | break; | 458 | break; |
| 431 | } | 459 | } |
| 460 | } | ||
| 432 | 461 | ||
| 433 | ++state.program_counter; | 462 | ++state.program_counter; |
| 434 | 463 | ||