1/* 2 * Copyright © 2022 Imagination Technologies Ltd. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 */ 23 24#include <assert.h> 25#include <stdbool.h> 26#include <stddef.h> 27#include <stdlib.h> 28 29#include "rogue_shader.h" 30#include "rogue_instr.h" 31#include "rogue_regalloc.h" 32#include "rogue_util.h" 33#include "util/ralloc.h" 34 35/** 36 * \file rogue_shader.c 37 * 38 * \brief Contains functions to manipulate Rogue shaders. 39 */ 40 41/** 42 * \brief Counts how many times an instruction is used in a shader. 43 * 44 * \param[in] shader The shader containing instructions to count. 45 * \param[in] opcode The opcode of the instruction to be counted. 46 * \return The number of times "opcode" is present, or 0 on error. 47 */ 48size_t rogue_shader_instr_count_type(const struct rogue_shader *shader, 49 enum rogue_opcode opcode) 50{ 51 size_t count = 0U; 52 53 ASSERT_OPCODE_RANGE(opcode); 54 55 foreach_instr (instr, &shader->instr_list) 56 if (instr->opcode == opcode) 57 ++count; 58 59 return count; 60} 61 62/** 63 * \brief Allocates and sets up a Rogue shader. 64 * 65 * \param[in] stage The shader stage. 66 * \return A rogue_shader* if successful, or NULL if unsuccessful. 67 */ 68struct rogue_shader *rogue_shader_create(struct rogue_build_ctx *ctx, 69 gl_shader_stage stage) 70{ 71 struct rogue_shader *shader; 72 73 if (!ctx) 74 return NULL; 75 76 shader = rzalloc_size(ctx, sizeof(*shader)); 77 if (!shader) 78 return NULL; 79 80 shader->stage = stage; 81 82 list_inithead(&shader->instr_list); 83 84 shader->ctx = ctx; 85 shader->ra = rogue_ra_init(shader); 86 if (!shader->ra) { 87 ralloc_free(shader); 88 return NULL; 89 } 90 91 return shader; 92} 93 94/** 95 * \brief Creates an instruction and appends it to a Rogue shader. 96 * 97 * \param[in] shader The shader. 98 * \param[in] opcode The instruction opcode. 99 * \return A rogue_instr* if successful, or NULL if unsuccessful. 100 */ 101struct rogue_instr *rogue_shader_insert(struct rogue_shader *shader, 102 enum rogue_opcode opcode) 103{ 104 struct rogue_instr *instr = rogue_instr_create(shader, opcode); 105 if (!instr) 106 return NULL; 107 108 list_addtail(&instr->node, &shader->instr_list); 109 110 return instr; 111} 112 113size_t rogue_acquire_drc(struct rogue_shader *shader) 114{ 115 size_t drc; 116 117 /* If both DRCs are in use, we have a problem. */ 118 if (shader->drc_used[0] && shader->drc_used[1]) 119 return SIZE_MAX; 120 121 drc = !shader->drc_used[0] ? 0 : 1; 122 shader->drc_used[drc] = true; 123 124 return drc; 125} 126 127void rogue_release_drc(struct rogue_shader *shader, size_t drc) 128{ 129 assert(drc < ROGUE_NUM_DRCS); 130 assert(shader->drc_used[drc]); 131 132 shader->drc_used[drc] = false; 133} 134