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