summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/PixelShaderGen.h
blob: e5dd43d754ed9d398e40cce473f8e2d5cb3b9b1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Copyright 2008 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include "Common/CommonTypes.h"
#include "VideoCommon/LightingShaderGen.h"
#include "VideoCommon/ShaderGenCommon.h"

enum class APIType;
enum class AlphaTestOp : u32;
enum class AlphaTestResult;
enum class CompareMode : u32;
enum class DstBlendFactor : u32;
enum class EmulatedZ : u32;
enum class FogProjection : u32;
enum class FogType : u32;
enum class KonstSel : u32;
enum class RasColorChan : u32;
enum class SrcBlendFactor : u32;
enum class ZTexOp : u32;

#pragma pack(1)
struct pixel_shader_uid_data
{
  // TODO: Optimize field order for easy access!

  u32 num_values;  // TODO: Shouldn't be a u32
  u32 NumValues() const { return num_values; }
  u32 pad0 : 4;
  u32 useDstAlpha : 1;
  u32 no_dual_src : 1;
  AlphaTestResult Pretest : 2;
  u32 nIndirectStagesUsed : 4;
  u32 genMode_numtexgens : 4;
  u32 genMode_numtevstages : 4;
  u32 genMode_numindstages : 3;
  CompareMode alpha_test_comp0 : 3;
  CompareMode alpha_test_comp1 : 3;
  AlphaTestOp alpha_test_logic : 2;
  FogProjection fog_proj : 1;

  FogType fog_fsel : 3;
  u32 fog_RangeBaseEnabled : 1;
  ZTexOp ztex_op : 2;
  u32 per_pixel_depth : 1;
  EmulatedZ ztest : 3;
  u32 bounding_box : 1;
  u32 zfreeze : 1;
  u32 numColorChans : 2;
  u32 rgba6_format : 1;
  u32 dither : 1;
  u32 uint_output : 1;
  u32 blend_enable : 1;                       // Only used with shader_framebuffer_fetch blend
  SrcBlendFactor blend_src_factor : 3;        // Only used with shader_framebuffer_fetch blend
  SrcBlendFactor blend_src_factor_alpha : 3;  // Only used with shader_framebuffer_fetch blend
  DstBlendFactor blend_dst_factor : 3;        // Only used with shader_framebuffer_fetch blend
  DstBlendFactor blend_dst_factor_alpha : 3;  // Only used with shader_framebuffer_fetch blend
  u32 blend_subtract : 1;                     // Only used with shader_framebuffer_fetch blend
  u32 blend_subtract_alpha : 1;               // Only used with shader_framebuffer_fetch blend
  u32 emulate_logic_op_with_blend : 1;        // Only used with logic op blend emulation
  u32 logic_op_enable : 1;                    // Only used with shader_framebuffer_fetch logic ops
  u32 logic_op_mode : 4;  // Only used with shader_framebuffer_fetch logic ops and blend emulation

  u32 texMtxInfo_n_projection : 8;  // 8x1 bit
  u32 tevindref_bi0 : 3;
  u32 tevindref_bc0 : 3;
  u32 tevindref_bi1 : 3;
  u32 tevindref_bc1 : 3;
  u32 tevindref_bi2 : 3;
  u32 tevindref_bc2 : 3;
  u32 tevindref_bi3 : 3;
  u32 tevindref_bc3 : 3;

  void SetTevindrefValues(int index, u32 texcoord, u32 texmap)
  {
    if (index == 0)
    {
      tevindref_bc0 = texcoord;
      tevindref_bi0 = texmap;
    }
    else if (index == 1)
    {
      tevindref_bc1 = texcoord;
      tevindref_bi1 = texmap;
    }
    else if (index == 2)
    {
      tevindref_bc2 = texcoord;
      tevindref_bi2 = texmap;
    }
    else if (index == 3)
    {
      tevindref_bc3 = texcoord;
      tevindref_bi3 = texmap;
    }
  }

  u32 GetTevindirefCoord(int index) const
  {
    if (index == 0)
      return tevindref_bc0;
    else if (index == 1)
      return tevindref_bc1;
    else if (index == 2)
      return tevindref_bc2;
    else if (index == 3)
      return tevindref_bc3;
    return 0;
  }

  u32 GetTevindirefMap(int index) const
  {
    if (index == 0)
      return tevindref_bi0;
    else if (index == 1)
      return tevindref_bi1;
    else if (index == 2)
      return tevindref_bi2;
    else if (index == 3)
      return tevindref_bi3;
    return 0;
  }

  struct
  {
    // TODO: Can save a lot space by removing the padding bits
    u32 cc : 24;
    u32 ac : 24;  // tswap and rswap are left blank (decoded into the swap fields below)

    u32 tevorders_texmap : 3;
    u32 tevorders_texcoord : 3;
    u32 tevorders_enable : 1;
    RasColorChan tevorders_colorchan : 3;
    u32 pad1 : 7;

    // TODO: We could save space by storing the 4 swap tables elsewhere and only storing references
    // to which table is used (the tswap and rswap fields), instead of duplicating them here
    u32 tevind : 21;
    ColorChannel ras_swap_r : 2;
    ColorChannel ras_swap_g : 2;
    ColorChannel ras_swap_b : 2;
    ColorChannel ras_swap_a : 2;
    u32 pad2 : 2;

    ColorChannel tex_swap_r : 2;
    ColorChannel tex_swap_g : 2;
    ColorChannel tex_swap_b : 2;
    ColorChannel tex_swap_a : 2;
    KonstSel tevksel_kc : 5;
    KonstSel tevksel_ka : 5;
    u32 pad3 : 14;
  } stagehash[16];

  LightingUidData lighting;
};
#pragma pack()

using PixelShaderUid = ShaderUid<pixel_shader_uid_data>;

void WriteCustomShaderStructImpl(ShaderCode* out, u32 num_stages, bool per_pixel_lighting,
                                 const pixel_shader_uid_data* uid_data);

ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& host_config,
                                   const pixel_shader_uid_data* uid_data,
                                   const CustomPixelShaderContents& custom_details);
void WritePixelShaderCommonHeader(ShaderCode& out, APIType api_type,
                                  const ShaderHostConfig& host_config, bool bounding_box,
                                  const CustomPixelShaderContents& custom_details);
void ClearUnusedPixelShaderUidBits(APIType api_type, const ShaderHostConfig& host_config,
                                   PixelShaderUid* uid);
PixelShaderUid GetPixelShaderUid();