summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/vertex_shader.cpp75
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