1 /*
2 * Copyright 2009 Nicolai Haehnle.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "radeon_code.h"
7
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11
12 #include "radeon_program.h"
13
rc_constants_init(struct rc_constant_list * c)14 void rc_constants_init(struct rc_constant_list * c)
15 {
16 memset(c, 0, sizeof(*c));
17 }
18
19 /**
20 * Copy a constants structure, assuming that the destination structure
21 * is not initialized.
22 */
rc_constants_copy(struct rc_constant_list * dst,struct rc_constant_list * src)23 void rc_constants_copy(struct rc_constant_list * dst, struct rc_constant_list * src)
24 {
25 dst->Constants = malloc(sizeof(struct rc_constant) * src->Count);
26 memcpy(dst->Constants, src->Constants, sizeof(struct rc_constant) * src->Count);
27 dst->Count = src->Count;
28 dst->_Reserved = src->Count;
29 }
30
rc_constants_destroy(struct rc_constant_list * c)31 void rc_constants_destroy(struct rc_constant_list * c)
32 {
33 free(c->Constants);
34 memset(c, 0, sizeof(*c));
35 }
36
rc_constants_add(struct rc_constant_list * c,struct rc_constant * constant)37 unsigned rc_constants_add(struct rc_constant_list * c, struct rc_constant * constant)
38 {
39 unsigned index = c->Count;
40
41 if (c->Count >= c->_Reserved) {
42 struct rc_constant * newlist;
43
44 c->_Reserved = c->_Reserved * 2;
45 if (!c->_Reserved)
46 c->_Reserved = 16;
47
48 newlist = malloc(sizeof(struct rc_constant) * c->_Reserved);
49 memcpy(newlist, c->Constants, sizeof(struct rc_constant) * c->Count);
50
51 free(c->Constants);
52 c->Constants = newlist;
53 }
54
55 c->Constants[index] = *constant;
56 c->Count++;
57
58 return index;
59 }
60
61
62 /**
63 * Add a state vector to the constant list, while trying to avoid duplicates.
64 */
rc_constants_add_state(struct rc_constant_list * c,unsigned state0,unsigned state1)65 unsigned rc_constants_add_state(struct rc_constant_list * c, unsigned state0, unsigned state1)
66 {
67 unsigned index;
68 struct rc_constant constant;
69
70 for(index = 0; index < c->Count; ++index) {
71 if (c->Constants[index].Type == RC_CONSTANT_STATE) {
72 if (c->Constants[index].u.State[0] == state0 &&
73 c->Constants[index].u.State[1] == state1)
74 return index;
75 }
76 }
77
78 memset(&constant, 0, sizeof(constant));
79 constant.Type = RC_CONSTANT_STATE;
80 constant.UseMask = RC_MASK_XYZW;
81 constant.u.State[0] = state0;
82 constant.u.State[1] = state1;
83
84 return rc_constants_add(c, &constant);
85 }
86
87
88 /**
89 * Add an immediate vector to the constant list, while trying to avoid
90 * duplicates.
91 */
rc_constants_add_immediate_vec4(struct rc_constant_list * c,const float * data)92 unsigned rc_constants_add_immediate_vec4(struct rc_constant_list * c, const float * data)
93 {
94 unsigned index;
95 struct rc_constant constant;
96
97 for(index = 0; index < c->Count; ++index) {
98 if (c->Constants[index].Type == RC_CONSTANT_IMMEDIATE) {
99 if (!memcmp(c->Constants[index].u.Immediate, data, sizeof(float)*4))
100 return index;
101 }
102 }
103
104 memset(&constant, 0, sizeof(constant));
105 constant.Type = RC_CONSTANT_IMMEDIATE;
106 constant.UseMask = RC_MASK_XYZW;
107 memcpy(constant.u.Immediate, data, sizeof(float) * 4);
108
109 return rc_constants_add(c, &constant);
110 }
111
112
113 /**
114 * Add an immediate scalar to the constant list, while trying to avoid
115 * duplicates.
116 */
rc_constants_add_immediate_scalar(struct rc_constant_list * c,float data,unsigned * swizzle)117 unsigned rc_constants_add_immediate_scalar(struct rc_constant_list * c, float data, unsigned * swizzle)
118 {
119 unsigned index, free_comp;
120 int free_index = -1;
121 struct rc_constant constant;
122
123 for(index = 0; index < c->Count; ++index) {
124 if (c->Constants[index].Type == RC_CONSTANT_IMMEDIATE) {
125 unsigned comp;
126 for(comp = 0; comp < 4; ++comp) {
127 if (c->Constants[index].UseMask & 1 << comp) {
128 if (c->Constants[index].u.Immediate[comp] == data) {
129 *swizzle = RC_MAKE_SWIZZLE_SMEAR(comp);
130 return index;
131 }
132 } else {
133 if (free_index == -1) {
134 free_index = index;
135 free_comp = comp;
136 }
137 }
138 }
139 }
140 }
141
142 if (free_index >= 0) {
143 c->Constants[free_index].u.Immediate[free_comp] = data;
144 c->Constants[free_index].UseMask |= 1 << free_comp;
145 *swizzle = RC_MAKE_SWIZZLE_SMEAR(free_comp);
146 return free_index;
147 }
148
149 memset(&constant, 0, sizeof(constant));
150 constant.Type = RC_CONSTANT_IMMEDIATE;
151 constant.UseMask = RC_MASK_X;
152 constant.u.Immediate[0] = data;
153 *swizzle = RC_SWIZZLE_XXXX;
154
155 return rc_constants_add(c, &constant);
156 }
157
swizzle_char(unsigned swz)158 static char swizzle_char(unsigned swz)
159 {
160 switch (swz) {
161 case RC_SWIZZLE_X:
162 return 'x';
163 case RC_SWIZZLE_Y:
164 return 'y';
165 case RC_SWIZZLE_Z:
166 return 'z';
167 case RC_SWIZZLE_W:
168 return 'w';
169 default:
170 return 'u';
171 }
172 }
173
rc_constants_print(struct rc_constant_list * c,struct const_remap * r)174 void rc_constants_print(struct rc_constant_list *c, struct const_remap *r)
175 {
176 for (unsigned i = 0; i < c->Count; i++) {
177 if (c->Constants[i].Type == RC_CONSTANT_IMMEDIATE) {
178 float *values = c->Constants[i].u.Immediate;
179 fprintf(stderr, "CONST[%u] = {", i);
180 for (unsigned chan = 0; chan < 4; chan++) {
181 if (c->Constants[i].UseMask & 1 << chan)
182 fprintf(stderr, "%11.6f ", values[chan]);
183 else
184 fprintf(stderr, " unused ");
185 }
186 fprintf(stderr, "}\n");
187 }
188 if (r && c->Constants[i].Type == RC_CONSTANT_EXTERNAL) {
189 fprintf(stderr, "CONST[%u] = {", i);
190 for (unsigned chan = 0; chan < 4; chan++) {
191 fprintf(stderr, "CONST[%i].%c ", r[i].index[chan],
192 swizzle_char(r[i].swizzle[chan]));
193 }
194 fprintf(stderr, " }\n");
195 }
196 }
197 }
198