| 2626 | } |
| 2627 | |
| 2628 | void reshadefx::codegen::optimize_bindings() |
| 2629 | { |
| 2630 | struct sampler_group |
| 2631 | { |
| 2632 | std::vector<function *> vs_entry_points; |
| 2633 | std::vector<function *> ps_entry_points; |
| 2634 | std::vector<id> vs_referenced_samplers; |
| 2635 | }; |
| 2636 | |
| 2637 | std::vector<sampler_group> sampler_groups; |
| 2638 | |
| 2639 | // Build a list of samplers referenced by all vertex and pixel shader combinations |
| 2640 | for (const technique &tech : _module.techniques) |
| 2641 | { |
| 2642 | for (const pass &pass : tech.passes) |
| 2643 | { |
| 2644 | if (!pass.cs_entry_point.empty()) |
| 2645 | continue; |
| 2646 | |
| 2647 | function *const vs = find_function(pass.vs_entry_point); |
| 2648 | function *const ps = !pass.ps_entry_point.empty() ? find_function(pass.ps_entry_point) : nullptr; |
| 2649 | |
| 2650 | bool has_vs_entry_point = false; |
| 2651 | bool has_ps_entry_point = false; |
| 2652 | auto group_it = std::find_if(sampler_groups.begin(), sampler_groups.end(), |
| 2653 | [vs, ps, &has_vs_entry_point, &has_ps_entry_point](const sampler_group &group) { |
| 2654 | has_vs_entry_point = std::find(group.vs_entry_points.begin(), group.vs_entry_points.end(), vs) != group.vs_entry_points.end(); |
| 2655 | has_ps_entry_point = std::find(group.ps_entry_points.begin(), group.ps_entry_points.end(), ps) != group.ps_entry_points.end(); |
| 2656 | return has_vs_entry_point || has_ps_entry_point; |
| 2657 | }); |
| 2658 | if (sampler_groups.end() == group_it) |
| 2659 | group_it = sampler_groups.insert(sampler_groups.end(), sampler_group {}); |
| 2660 | |
| 2661 | if (!has_vs_entry_point) |
| 2662 | group_it->vs_entry_points.push_back(vs); |
| 2663 | if (!pass.ps_entry_point.empty() && !has_ps_entry_point) |
| 2664 | group_it->ps_entry_points.push_back(ps); |
| 2665 | |
| 2666 | std::vector<codegen::id> vs_referenced_samplers; |
| 2667 | std::set_union(group_it->vs_referenced_samplers.begin(), group_it->vs_referenced_samplers.end(), vs->referenced_samplers.begin(), vs->referenced_samplers.end(), std::back_inserter(vs_referenced_samplers)); |
| 2668 | group_it->vs_referenced_samplers = std::move(vs_referenced_samplers); |
| 2669 | } |
| 2670 | } |
| 2671 | |
| 2672 | for (const sampler_group &group : sampler_groups) |
| 2673 | { |
| 2674 | for (function *const vs_entry_point : group.vs_entry_points) |
| 2675 | { |
| 2676 | for (size_t binding = 0; binding < std::min(vs_entry_point->referenced_samplers.size(), group.vs_referenced_samplers.size()); ++binding) |
| 2677 | { |
| 2678 | if (vs_entry_point->referenced_samplers[binding] != group.vs_referenced_samplers[binding]) |
| 2679 | vs_entry_point->referenced_samplers.insert(vs_entry_point->referenced_samplers.begin() + binding, 0); |
| 2680 | } |
| 2681 | } |
| 2682 | |
| 2683 | for (function *const ps_entry_point : group.ps_entry_points) |
| 2684 | { |
| 2685 | // Add samplers referenced in vertex shader to all pixel shaders that are used with it, while keeping the vertex shader ones at the front to ensure binding compatibility |