• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2024 Imagination Technologies Ltd.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 
7 /**
8  * \file pco.c
9  *
10  * \brief Main compiler interface.
11  */
12 
13 #include "compiler/glsl_types.h"
14 #include "pco.h"
15 #include "pco_internal.h"
16 #include "util/hash_table.h"
17 #include "util/list.h"
18 #include "util/macros.h"
19 #include "util/ralloc.h"
20 
21 #include <assert.h>
22 #include <stdbool.h>
23 
24 /**
25  * \brief PCO compiler context destructor.
26  *
27  * \param[in,out] ptr PCO compiler context pointer.
28  */
pco_ctx_destructor(UNUSED void * ptr)29 static void pco_ctx_destructor(UNUSED void *ptr)
30 {
31    glsl_type_singleton_decref();
32 }
33 
34 /**
35  * \brief Allocates and sets up a PCO compiler context.
36  *
37  * \param[in] dev_info Device info.
38  * \param[in] mem_ctx Ralloc memory allocation context.
39  * \return The PCO compiler context, or NULL on failure.
40  */
pco_ctx_create(const struct pvr_device_info * dev_info,void * mem_ctx)41 pco_ctx *pco_ctx_create(const struct pvr_device_info *dev_info, void *mem_ctx)
42 {
43    pco_ctx *ctx = rzalloc_size(mem_ctx, sizeof(*ctx));
44 
45    ctx->dev_info = dev_info;
46 
47    pco_debug_init();
48 
49 #ifndef NDEBUG
50    /* Ensure NIR debug variables are processed. */
51    nir_process_debug_variable();
52 #endif /* NDEBUG */
53 
54    pco_setup_spirv_options(dev_info, &ctx->spirv_options);
55    pco_setup_nir_options(dev_info, &ctx->nir_options);
56 
57    glsl_type_singleton_init_or_ref();
58    ralloc_set_destructor(ctx, pco_ctx_destructor);
59 
60    return ctx;
61 }
62 
63 /**
64  * \brief Returns the device/core-specific SPIR-V to NIR options for a PCO
65  * compiler context.
66  *
67  * \param[in] ctx PCO compiler context.
68  * \return The device/core-specific SPIR-V to NIR options.
69  */
pco_spirv_options(pco_ctx * ctx)70 const struct spirv_to_nir_options *pco_spirv_options(pco_ctx *ctx)
71 {
72    return &ctx->spirv_options;
73 }
74 
75 /**
76  * \brief Returns the device/core-specific NIR options for a PCO compiler
77  * context.
78  *
79  * \param[in] ctx PCO compiler context.
80  * \return The device/core-specific NIR options.
81  */
pco_nir_options(pco_ctx * ctx)82 const nir_shader_compiler_options *pco_nir_options(pco_ctx *ctx)
83 {
84    return &ctx->nir_options;
85 }
86 
87 /**
88  * \brief Allocates and sets up a PCO shader from a NIR shader.
89  *
90  * \param[in] ctx PCO compiler context.
91  * \param[in] nir The NIR shader.
92  * \return The PCO shader, or NULL on failure.
93  */
pco_shader_create(pco_ctx * ctx,nir_shader * nir,void * mem_ctx)94 pco_shader *pco_shader_create(pco_ctx *ctx, nir_shader *nir, void *mem_ctx)
95 {
96    pco_shader *shader = rzalloc_size(mem_ctx, sizeof(*shader));
97 
98    shader->ctx = ctx;
99    shader->nir = nir;
100    shader->stage = nir->info.stage;
101    shader->name = ralloc_strdup(shader, nir->info.name);
102    shader->is_internal = nir->info.internal;
103    shader->is_grouped = false;
104    list_inithead(&shader->funcs);
105 
106    return shader;
107 }
108 
109 /**
110  * \brief Sets up a PCO cf node.
111  *
112  * \param[in,out] cf_node PCO cf node.
113  * \param[in] type CF node type.
114  */
init_cf_node(pco_cf_node * cf_node,enum pco_cf_node_type type)115 static inline void init_cf_node(pco_cf_node *cf_node,
116                                 enum pco_cf_node_type type)
117 {
118    cf_node->type = type;
119    cf_node->parent = NULL;
120 }
121 
122 /**
123  * \brief Allocates and sets up a PCO function.
124  *
125  * \param[in,out] shader PCO shader.
126  * \param[in] type The function type.
127  * \param[in] num_params The number of parameters.
128  * \return The PCO function, or NULL on failure.
129  */
pco_func_create(pco_shader * shader,enum pco_func_type type,unsigned num_params)130 pco_func *pco_func_create(pco_shader *shader,
131                           enum pco_func_type type,
132                           unsigned num_params)
133 {
134    pco_func *func = rzalloc_size(shader, sizeof(*func));
135    pco_func *preamble = pco_preamble(shader);
136 
137    /* Add the function to the shader; preamble goes first, then entrypoint.
138     * The rest of the functions will get appended.
139     */
140    if (type == PCO_FUNC_TYPE_PREAMBLE) {
141       assert(!preamble);
142       list_add(&func->link, &shader->funcs);
143    } else if (type == PCO_FUNC_TYPE_ENTRYPOINT) {
144       assert(!pco_entrypoint(shader));
145       list_add(&func->link, !preamble ? &shader->funcs : &preamble->link);
146    } else {
147       list_addtail(&func->link, &shader->funcs);
148    }
149 
150    init_cf_node(&func->cf_node, PCO_CF_NODE_TYPE_FUNC);
151    func->parent_shader = shader;
152    func->type = type;
153    func->index = shader->next_func++;
154 
155    list_inithead(&func->body);
156 
157    func->num_params = num_params;
158    if (num_params) {
159       func->params =
160          rzalloc_array_size(func, sizeof(*func->params), num_params);
161    }
162 
163    func->vec_infos = _mesa_hash_table_u64_create(func);
164 
165    func->enc_offset = ~0U;
166 
167    return func;
168 }
169 
170 /**
171  * \brief Allocates and sets up a PCO block.
172  *
173  * \param[in,out] func Parent function.
174  * \return The PCO block, or NULL on failure.
175  */
pco_block_create(pco_func * func)176 pco_block *pco_block_create(pco_func *func)
177 {
178    pco_block *block = rzalloc_size(func, sizeof(*block));
179 
180    init_cf_node(&block->cf_node, PCO_CF_NODE_TYPE_BLOCK);
181    block->parent_func = func;
182    list_inithead(&block->instrs);
183    block->index = func->next_block++;
184 
185    return block;
186 }
187 
188 /**
189  * \brief Allocates and sets up a PCO if construct.
190  *
191  * \param[in,out] func Parent function.
192  * \return The PCO if construct, or NULL on failure.
193  */
pco_if_create(pco_func * func)194 pco_if *pco_if_create(pco_func *func)
195 {
196    pco_if *pif = rzalloc_size(func, sizeof(*pif));
197 
198    init_cf_node(&pif->cf_node, PCO_CF_NODE_TYPE_IF);
199    pif->parent_func = func;
200    list_inithead(&pif->then_body);
201    list_inithead(&pif->else_body);
202    pif->index = func->next_if++;
203 
204    return pif;
205 }
206 
207 /**
208  * \brief Allocates and sets up a PCO loop.
209  *
210  * \param[in,out] func Parent function.
211  * \return The PCO loop, or NULL on failure.
212  */
pco_loop_create(pco_func * func)213 pco_loop *pco_loop_create(pco_func *func)
214 {
215    pco_loop *loop = rzalloc_size(func, sizeof(*loop));
216 
217    init_cf_node(&loop->cf_node, PCO_CF_NODE_TYPE_LOOP);
218    loop->parent_func = func;
219    list_inithead(&loop->body);
220    loop->index = func->next_loop++;
221 
222    return loop;
223 }
224 
225 /**
226  * \brief Allocates and sets up a PCO instruction.
227  *
228  * \param[in,out] func Parent function.
229  * \param[in] op Instruction op.
230  * \param[in] num_dests Number of destinations.
231  * \param[in] num_srcs Number of sources.
232  * \return The PCO instruction, or NULL on failure.
233  */
pco_instr_create(pco_func * func,enum pco_op op,unsigned num_dests,unsigned num_srcs)234 pco_instr *pco_instr_create(pco_func *func,
235                             enum pco_op op,
236                             unsigned num_dests,
237                             unsigned num_srcs)
238 {
239    pco_instr *instr;
240    unsigned size = sizeof(*instr);
241    size += num_dests * sizeof(*instr->dest);
242    size += num_srcs * sizeof(*instr->src);
243 
244    instr = rzalloc_size(func, size);
245 
246    instr->parent_func = func;
247 
248    instr->op = op;
249 
250    instr->num_dests = num_dests;
251    instr->dest = (pco_ref *)(instr + 1);
252 
253    instr->num_srcs = num_srcs;
254    instr->src = instr->dest + num_dests;
255 
256    list_inithead(&instr->phi_srcs);
257 
258    instr->index = func->next_instr++;
259 
260    return instr;
261 }
262 
263 /**
264  * \brief Allocates and sets up a PCO instruction group.
265  *
266  * \param[in,out] func Parent function.
267  * \return The PCO instruction group, or NULL on failure.
268  */
pco_igrp_create(pco_func * func)269 pco_igrp *pco_igrp_create(pco_func *func)
270 {
271    pco_igrp *igrp = rzalloc_size(func, sizeof(*igrp));
272 
273    igrp->parent_func = func;
274    igrp->index = func->next_igrp++;
275 
276    return igrp;
277 }
278 
279 /**
280  * \brief Deletes a PCO instruction.
281  *
282  * \param[in,out] instr PCO instruction.
283  */
pco_instr_delete(pco_instr * instr)284 void pco_instr_delete(pco_instr *instr)
285 {
286    list_del(&instr->link);
287    ralloc_free(instr);
288 }
289 
290 /**
291  * \brief Returns the shader data.
292  *
293  * \param[in] shader PCO shader.
294  */
pco_shader_data(pco_shader * shader)295 pco_data *pco_shader_data(pco_shader *shader)
296 {
297    return &shader->data;
298 }
299