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