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 <stdint.h> 27bf215546Sopenharmony_ci#include <stdio.h> 28bf215546Sopenharmony_ci#include <string.h> 29bf215546Sopenharmony_ci 30bf215546Sopenharmony_ci#include "pvr_device_info.h" 31bf215546Sopenharmony_ci#include "pvr_pds.h" 32bf215546Sopenharmony_ci#include "pvr_rogue_pds_defs.h" 33bf215546Sopenharmony_ci#include "pvr_rogue_pds_disasm.h" 34bf215546Sopenharmony_ci#include "pvr_rogue_pds_encode.h" 35bf215546Sopenharmony_ci#include "util/log.h" 36bf215546Sopenharmony_ci#include "util/macros.h" 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ci#define R32_C(x) ((x) + PVR_ROGUE_PDSINST_REGS32_CONST32_LOWER) 39bf215546Sopenharmony_ci#define R32_T(x) ((x) + PVR_ROGUE_PDSINST_REGS32_TEMP32_LOWER) 40bf215546Sopenharmony_ci#define R32_P(x) ((x) + PVR_ROGUE_PDSINST_REGS32_PTEMP32_LOWER) 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci#define R32TP_T(x) ((x) + PVR_ROGUE_PDSINST_REGS32TP_TEMP32_LOWER) 43bf215546Sopenharmony_ci#define R32TP_P(x) ((x) + PVR_ROGUE_PDSINST_REGS32TP_PTEMP32_LOWER) 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci#define R64_C(x) ((x) + PVR_ROGUE_PDSINST_REGS64_CONST64_LOWER) 46bf215546Sopenharmony_ci#define R64_T(x) ((x) + PVR_ROGUE_PDSINST_REGS64_TEMP64_LOWER) 47bf215546Sopenharmony_ci#define R64_P(x) ((x) + PVR_ROGUE_PDSINST_REGS64_PTEMP64_LOWER) 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci#define R64TP_T(x) ((x) + PVR_ROGUE_PDSINST_REGS64TP_TEMP64_LOWER) 50bf215546Sopenharmony_ci#define R64TP_P(x) ((x) + PVR_ROGUE_PDSINST_REGS64TP_PTEMP64_LOWER) 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_ci/* 32-bit PTemp index for draw indirect base instance. */ 53bf215546Sopenharmony_ci#define PVR_INDIRECT_BASE_INSTANCE_PTEMP 1U 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_ci/* Number of constants to reserve per DDMAD instruction in the PDS Vertex. */ 56bf215546Sopenharmony_ci#define PVR_PDS_DDMAD_NUM_CONSTS 8 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci#if defined(TRACE_PDS) 59bf215546Sopenharmony_ci/* Some macros for a pretty printing. */ 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci# define pvr_debug_pds_const(reg, size, annotation) \ 62bf215546Sopenharmony_ci mesa_logd("const[%d] @ (%dbits) %s", reg, size, annotation) 63bf215546Sopenharmony_ci# define pvr_debug_pds_temp(reg, size, annotation) \ 64bf215546Sopenharmony_ci mesa_logd("temp[%d] @ (%dbits) %s", reg, size, annotation) 65bf215546Sopenharmony_ci# define pvr_debug_pds_note(...) mesa_logd(" // " __VA_ARGS__) 66bf215546Sopenharmony_ci# define pvr_debug_pds_flag(flags, flag) \ 67bf215546Sopenharmony_ci { \ 68bf215546Sopenharmony_ci if ((flags & flag) == flag) \ 69bf215546Sopenharmony_ci mesa_logd(" > " #flag); \ 70bf215546Sopenharmony_ci } 71bf215546Sopenharmony_ci# define pvr_debug(annotation) mesa_logd(annotation) 72bf215546Sopenharmony_ci 73bf215546Sopenharmony_ci#else 74bf215546Sopenharmony_ci# define pvr_debug_pds_const(reg, size, annotation) 75bf215546Sopenharmony_ci# define pvr_debug_pds_temp(reg, size, annotation) 76bf215546Sopenharmony_ci# define pvr_debug_pds_note(...) 77bf215546Sopenharmony_ci# define pvr_debug_pds_flag(flags, flag) 78bf215546Sopenharmony_ci# define pvr_debug(annotation) 79bf215546Sopenharmony_ci#endif 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_cistruct pvr_pds_const_map_entry_write_state { 82bf215546Sopenharmony_ci const struct pvr_pds_info *PDS_info; 83bf215546Sopenharmony_ci struct pvr_const_map_entry *entry; 84bf215546Sopenharmony_ci size_t size_of_last_entry_in_bytes; 85bf215546Sopenharmony_ci uint32_t entry_count; 86bf215546Sopenharmony_ci size_t entries_size_in_bytes; 87bf215546Sopenharmony_ci}; 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_cistatic void pvr_init_pds_const_map_entry_write_state( 90bf215546Sopenharmony_ci struct pvr_pds_info *PDS_info, 91bf215546Sopenharmony_ci struct pvr_pds_const_map_entry_write_state *entry_write_state) 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci entry_write_state->PDS_info = PDS_info; 94bf215546Sopenharmony_ci entry_write_state->entry = PDS_info->entries; 95bf215546Sopenharmony_ci entry_write_state->size_of_last_entry_in_bytes = 0; 96bf215546Sopenharmony_ci entry_write_state->entry_count = 0; 97bf215546Sopenharmony_ci entry_write_state->entries_size_in_bytes = 0; 98bf215546Sopenharmony_ci} 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci/* Returns a pointer to the next struct pvr_const_map_entry. */ 101bf215546Sopenharmony_cistatic void *pvr_prepare_next_pds_const_map_entry( 102bf215546Sopenharmony_ci struct pvr_pds_const_map_entry_write_state *entry_write_state, 103bf215546Sopenharmony_ci size_t size_of_next_entry_in_bytes) 104bf215546Sopenharmony_ci{ 105bf215546Sopenharmony_ci /* Move on to the next entry. */ 106bf215546Sopenharmony_ci uint8_t *next_entry = ((uint8_t *)entry_write_state->entry + 107bf215546Sopenharmony_ci entry_write_state->size_of_last_entry_in_bytes); 108bf215546Sopenharmony_ci entry_write_state->entry = (struct pvr_const_map_entry *)next_entry; 109bf215546Sopenharmony_ci 110bf215546Sopenharmony_ci entry_write_state->size_of_last_entry_in_bytes = size_of_next_entry_in_bytes; 111bf215546Sopenharmony_ci entry_write_state->entry_count++; 112bf215546Sopenharmony_ci entry_write_state->entries_size_in_bytes += size_of_next_entry_in_bytes; 113bf215546Sopenharmony_ci 114bf215546Sopenharmony_ci /* Check if we can write into the next entry. */ 115bf215546Sopenharmony_ci assert(entry_write_state->entries_size_in_bytes <= 116bf215546Sopenharmony_ci entry_write_state->PDS_info->entries_size_in_bytes); 117bf215546Sopenharmony_ci 118bf215546Sopenharmony_ci return entry_write_state->entry; 119bf215546Sopenharmony_ci} 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_cistatic void pvr_write_pds_const_map_entry_vertex_attribute_address( 122bf215546Sopenharmony_ci struct pvr_pds_const_map_entry_write_state *entry_write_state, 123bf215546Sopenharmony_ci const struct pvr_pds_vertex_dma *DMA, 124bf215546Sopenharmony_ci uint32_t const_val, 125bf215546Sopenharmony_ci bool use_robust_vertex_fetch) 126bf215546Sopenharmony_ci{ 127bf215546Sopenharmony_ci pvr_debug_pds_note("DMA %d dwords, stride %d, offset %d, bindingIdx %d", 128bf215546Sopenharmony_ci DMA->size_in_dwords, 129bf215546Sopenharmony_ci DMA->stride, 130bf215546Sopenharmony_ci DMA->offset, 131bf215546Sopenharmony_ci DMA->binding_index); 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci if (use_robust_vertex_fetch) { 134bf215546Sopenharmony_ci struct pvr_const_map_entry_robust_vertex_attribute_address 135bf215546Sopenharmony_ci *robust_attribute_entry; 136bf215546Sopenharmony_ci 137bf215546Sopenharmony_ci robust_attribute_entry = 138bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(entry_write_state, 139bf215546Sopenharmony_ci sizeof(*robust_attribute_entry)); 140bf215546Sopenharmony_ci robust_attribute_entry->type = 141bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_ROBUST_VERTEX_ATTRIBUTE_ADDRESS; 142bf215546Sopenharmony_ci robust_attribute_entry->const_offset = const_val; 143bf215546Sopenharmony_ci robust_attribute_entry->binding_index = DMA->binding_index; 144bf215546Sopenharmony_ci robust_attribute_entry->component_size_in_bytes = 145bf215546Sopenharmony_ci DMA->component_size_in_bytes; 146bf215546Sopenharmony_ci robust_attribute_entry->offset = DMA->offset; 147bf215546Sopenharmony_ci robust_attribute_entry->stride = DMA->stride; 148bf215546Sopenharmony_ci robust_attribute_entry->size_in_dwords = DMA->size_in_dwords; 149bf215546Sopenharmony_ci robust_attribute_entry->robustness_buffer_offset = 150bf215546Sopenharmony_ci DMA->robustness_buffer_offset; 151bf215546Sopenharmony_ci } else { 152bf215546Sopenharmony_ci struct pvr_const_map_entry_vertex_attribute_address *attribute_entry; 153bf215546Sopenharmony_ci 154bf215546Sopenharmony_ci attribute_entry = 155bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(entry_write_state, 156bf215546Sopenharmony_ci sizeof(*attribute_entry)); 157bf215546Sopenharmony_ci attribute_entry->type = 158bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTRIBUTE_ADDRESS; 159bf215546Sopenharmony_ci attribute_entry->const_offset = const_val; 160bf215546Sopenharmony_ci attribute_entry->binding_index = DMA->binding_index; 161bf215546Sopenharmony_ci attribute_entry->offset = DMA->offset; 162bf215546Sopenharmony_ci attribute_entry->stride = DMA->stride; 163bf215546Sopenharmony_ci attribute_entry->size_in_dwords = DMA->size_in_dwords; 164bf215546Sopenharmony_ci } 165bf215546Sopenharmony_ci} 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_cistatic ALWAYS_INLINE uint32_t pvr_pds_encode_doutu(uint32_t cc, 168bf215546Sopenharmony_ci uint32_t end, 169bf215546Sopenharmony_ci uint32_t src0) 170bf215546Sopenharmony_ci{ 171bf215546Sopenharmony_ci return pvr_pds_inst_encode_dout(cc, 172bf215546Sopenharmony_ci end, 173bf215546Sopenharmony_ci 0, 174bf215546Sopenharmony_ci src0, 175bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DSTDOUT_DOUTU); 176bf215546Sopenharmony_ci} 177bf215546Sopenharmony_ci 178bf215546Sopenharmony_cistatic uint32_t 179bf215546Sopenharmony_cipvr_encode_burst(struct pvr_pds_const_map_entry_write_state *entry_write_state, 180bf215546Sopenharmony_ci bool last_DMA, 181bf215546Sopenharmony_ci bool halt, 182bf215546Sopenharmony_ci unsigned int const32, 183bf215546Sopenharmony_ci unsigned int const64, 184bf215546Sopenharmony_ci unsigned int dma_size_in_dwords, 185bf215546Sopenharmony_ci unsigned int destination, 186bf215546Sopenharmony_ci unsigned int store) 187bf215546Sopenharmony_ci{ 188bf215546Sopenharmony_ci uint32_t literal_value; 189bf215546Sopenharmony_ci 190bf215546Sopenharmony_ci /* Encode literal value. */ 191bf215546Sopenharmony_ci literal_value = dma_size_in_dwords 192bf215546Sopenharmony_ci << PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_BSIZE_SHIFT; 193bf215546Sopenharmony_ci literal_value |= destination 194bf215546Sopenharmony_ci << PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_AO_SHIFT; 195bf215546Sopenharmony_ci literal_value |= PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_CMODE_CACHED | 196bf215546Sopenharmony_ci store; 197bf215546Sopenharmony_ci 198bf215546Sopenharmony_ci if (last_DMA) 199bf215546Sopenharmony_ci literal_value |= PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTD_SRC1_LAST_EN; 200bf215546Sopenharmony_ci 201bf215546Sopenharmony_ci /* Create const map entry. */ 202bf215546Sopenharmony_ci struct pvr_const_map_entry_literal32 *literal_entry; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci literal_entry = pvr_prepare_next_pds_const_map_entry(entry_write_state, 205bf215546Sopenharmony_ci sizeof(*literal_entry)); 206bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 207bf215546Sopenharmony_ci literal_entry->const_offset = const32; 208bf215546Sopenharmony_ci literal_entry->literal_value = literal_value; 209bf215546Sopenharmony_ci 210bf215546Sopenharmony_ci /* Encode DOUTD */ 211bf215546Sopenharmony_ci return pvr_pds_inst_encode_dout(0, 212bf215546Sopenharmony_ci halt, 213bf215546Sopenharmony_ci R32_C(const32), 214bf215546Sopenharmony_ci R64_C(const64), 215bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DSTDOUT_DOUTD); 216bf215546Sopenharmony_ci} 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci#define pvr_encode_burst_cs(psDataEntry, \ 219bf215546Sopenharmony_ci last_DMA, \ 220bf215546Sopenharmony_ci halt, \ 221bf215546Sopenharmony_ci const32, \ 222bf215546Sopenharmony_ci const64, \ 223bf215546Sopenharmony_ci dma_size_in_dwords, \ 224bf215546Sopenharmony_ci destination) \ 225bf215546Sopenharmony_ci pvr_encode_burst( \ 226bf215546Sopenharmony_ci psDataEntry, \ 227bf215546Sopenharmony_ci last_DMA, \ 228bf215546Sopenharmony_ci halt, \ 229bf215546Sopenharmony_ci const32, \ 230bf215546Sopenharmony_ci const64, \ 231bf215546Sopenharmony_ci dma_size_in_dwords, \ 232bf215546Sopenharmony_ci destination, \ 233bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_COMMON_STORE) 234bf215546Sopenharmony_ci 235bf215546Sopenharmony_cistatic uint32_t pvr_encode_direct_write( 236bf215546Sopenharmony_ci struct pvr_pds_const_map_entry_write_state *entry_write_state, 237bf215546Sopenharmony_ci bool last_DMA, 238bf215546Sopenharmony_ci bool halt, 239bf215546Sopenharmony_ci unsigned int const32, 240bf215546Sopenharmony_ci unsigned int const64, 241bf215546Sopenharmony_ci uint32_t data_mask, 242bf215546Sopenharmony_ci unsigned int destination, 243bf215546Sopenharmony_ci uint32_t destination_store, 244bf215546Sopenharmony_ci const struct pvr_device_info *dev_info) 245bf215546Sopenharmony_ci{ 246bf215546Sopenharmony_ci struct pvr_const_map_entry_literal32 *literal_entry; 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci uint32_t instruction = 249bf215546Sopenharmony_ci pvr_pds_inst_encode_dout(0, 250bf215546Sopenharmony_ci halt, 251bf215546Sopenharmony_ci const32, 252bf215546Sopenharmony_ci const64, 253bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DSTDOUT_DOUTW); 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci literal_entry = pvr_prepare_next_pds_const_map_entry(entry_write_state, 256bf215546Sopenharmony_ci sizeof(*literal_entry)); 257bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 258bf215546Sopenharmony_ci literal_entry->const_offset = const32; 259bf215546Sopenharmony_ci literal_entry->literal_value = destination_store; 260bf215546Sopenharmony_ci 261bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, slc_mcu_cache_controls)) { 262bf215546Sopenharmony_ci literal_entry->literal_value |= 263bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_CMODE_CACHED; 264bf215546Sopenharmony_ci } 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci literal_entry->literal_value |= 267bf215546Sopenharmony_ci destination << PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_AO_SHIFT; 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci if (data_mask == 0x1) { 270bf215546Sopenharmony_ci literal_entry->literal_value |= 271bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_BSIZE_LOWER; 272bf215546Sopenharmony_ci } else if (data_mask == 0x2) { 273bf215546Sopenharmony_ci literal_entry->literal_value |= 274bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_BSIZE_UPPER; 275bf215546Sopenharmony_ci } else { 276bf215546Sopenharmony_ci literal_entry->literal_value |= 277bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_BSIZE_ALL64; 278bf215546Sopenharmony_ci } 279bf215546Sopenharmony_ci 280bf215546Sopenharmony_ci if (last_DMA) { 281bf215546Sopenharmony_ci literal_entry->literal_value |= 282bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_LAST_EN; 283bf215546Sopenharmony_ci } 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci return instruction; 286bf215546Sopenharmony_ci} 287bf215546Sopenharmony_ci 288bf215546Sopenharmony_ci/* Constant and Temporary register allocation 289bf215546Sopenharmony_ci * - reserve space for a 32-bit register or a 64-bit register 290bf215546Sopenharmony_ci * - returned indices are offsets to 32-bit register locations 291bf215546Sopenharmony_ci * - 64-bit registers need to be aligned to even indices. 292bf215546Sopenharmony_ci */ 293bf215546Sopenharmony_ci#define RESERVE_32BIT 1U 294bf215546Sopenharmony_ci#define RESERVE_64BIT 2U 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci#if defined(DEBUG) 297bf215546Sopenharmony_ci# define pvr_find_constant(usage, words, name) \ 298bf215546Sopenharmony_ci pvr_find_constant2(usage, words, name) 299bf215546Sopenharmony_ci# define pvr_get_temps(usage, words, name) pvr_get_temps2(usage, words, name) 300bf215546Sopenharmony_ci#else 301bf215546Sopenharmony_ci# define pvr_find_constant(usage, words, name) \ 302bf215546Sopenharmony_ci pvr_find_constant2(usage, words, NULL); 303bf215546Sopenharmony_ci# define pvr_get_temps(usage, words, name) pvr_get_temps2(usage, words, NULL) 304bf215546Sopenharmony_ci#endif 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_cistatic uint32_t 307bf215546Sopenharmony_cipvr_find_constant2(uint8_t *const_usage, uint8_t words, const char *const_name) 308bf215546Sopenharmony_ci{ 309bf215546Sopenharmony_ci uint32_t const_index = ~0U; 310bf215546Sopenharmony_ci uint32_t step = words; 311bf215546Sopenharmony_ci uint8_t mask = (1 << words) - 1; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci assert(words == 1 || words == 2); 314bf215546Sopenharmony_ci 315bf215546Sopenharmony_ci /* Find a register at 'step' alignment that satisfies the mask. */ 316bf215546Sopenharmony_ci for (uint32_t i = 0; i < PVR_MAX_VERTEX_ATTRIB_DMAS; i++) { 317bf215546Sopenharmony_ci for (uint32_t b = 0; b < PVR_PDS_DDMAD_NUM_CONSTS; b += step) { 318bf215546Sopenharmony_ci if ((const_usage[i] & (mask << b)) != 0) 319bf215546Sopenharmony_ci continue; 320bf215546Sopenharmony_ci const_usage[i] |= (mask << b); 321bf215546Sopenharmony_ci const_index = i * 8 + b; 322bf215546Sopenharmony_ci pvr_debug_pds_const(const_index, words * 32, const_name); 323bf215546Sopenharmony_ci return const_index; 324bf215546Sopenharmony_ci } 325bf215546Sopenharmony_ci } 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci unreachable("Unexpected: Space cannot be found for constant"); 328bf215546Sopenharmony_ci return ~0U; 329bf215546Sopenharmony_ci} 330bf215546Sopenharmony_ci 331bf215546Sopenharmony_ci#define PVR_MAX_PDS_TEMPS 32 332bf215546Sopenharmony_cistruct pvr_temp_usage { 333bf215546Sopenharmony_ci uint32_t temp_usage; 334bf215546Sopenharmony_ci uint8_t temp_used; 335bf215546Sopenharmony_ci uint8_t temps_needed; 336bf215546Sopenharmony_ci}; 337bf215546Sopenharmony_ci 338bf215546Sopenharmony_ci#define PVR_INVALID_TEMP UINT8_C(~0) 339bf215546Sopenharmony_ci 340bf215546Sopenharmony_cistatic uint8_t pvr_get_temps2(struct pvr_temp_usage *temps, 341bf215546Sopenharmony_ci uint8_t temps_needed, 342bf215546Sopenharmony_ci const char *temp_name) 343bf215546Sopenharmony_ci{ 344bf215546Sopenharmony_ci uint8_t step = temps_needed; 345bf215546Sopenharmony_ci uint8_t mask = (1 << temps_needed) - 1; 346bf215546Sopenharmony_ci 347bf215546Sopenharmony_ci assert(temps_needed == 1 || temps_needed == 2); 348bf215546Sopenharmony_ci assert(temps->temp_used + temps_needed <= PVR_MAX_PDS_TEMPS); 349bf215546Sopenharmony_ci 350bf215546Sopenharmony_ci for (uint8_t i = 0; i < PVR_MAX_PDS_TEMPS; i += step) { 351bf215546Sopenharmony_ci if ((temps->temp_usage & (mask << i)) != 0) 352bf215546Sopenharmony_ci continue; 353bf215546Sopenharmony_ci 354bf215546Sopenharmony_ci const size_t clzBits = 8 * sizeof(unsigned int); 355bf215546Sopenharmony_ci 356bf215546Sopenharmony_ci temps->temp_usage |= (mask << i); 357bf215546Sopenharmony_ci temps->temp_used += temps_needed; 358bf215546Sopenharmony_ci temps->temps_needed = 359bf215546Sopenharmony_ci clzBits - __builtin_clz((unsigned int)temps->temp_usage); 360bf215546Sopenharmony_ci 361bf215546Sopenharmony_ci pvr_debug_pds_temp(i, temps_needed * 32, temp_name); 362bf215546Sopenharmony_ci 363bf215546Sopenharmony_ci return i; 364bf215546Sopenharmony_ci } 365bf215546Sopenharmony_ci 366bf215546Sopenharmony_ci unreachable("Unexpected: Space cannot be found for temps"); 367bf215546Sopenharmony_ci return PVR_INVALID_TEMP; 368bf215546Sopenharmony_ci} 369bf215546Sopenharmony_ci 370bf215546Sopenharmony_ci/** 371bf215546Sopenharmony_ci * Wrapper macro to add a toggle for "data mode", allowing us to calculate the 372bf215546Sopenharmony_ci * size of a PDS program without actually attempting to store it. 373bf215546Sopenharmony_ci * 374bf215546Sopenharmony_ci * \param dest The array/memory pointer where the PDS program should be stored. 375bf215546Sopenharmony_ci * If the given code is NULL, automatically switch to count mode 376bf215546Sopenharmony_ci * instead of attempting to fill in unallocated memory. 377bf215546Sopenharmony_ci * \param counter The local counter that holds the total instruction count. 378bf215546Sopenharmony_ci * \param statement What function call/value should be stored at dest[counter] 379bf215546Sopenharmony_ci * when condition is false. 380bf215546Sopenharmony_ci */ 381bf215546Sopenharmony_ci 382bf215546Sopenharmony_ci#define PVR_PDS_MODE_TOGGLE(dest, counter, statement) \ 383bf215546Sopenharmony_ci if (!dest) { \ 384bf215546Sopenharmony_ci counter++; \ 385bf215546Sopenharmony_ci } else { \ 386bf215546Sopenharmony_ci dest[counter++] = statement; \ 387bf215546Sopenharmony_ci PVR_PDS_PRINT_INST(statement); \ 388bf215546Sopenharmony_ci } 389bf215546Sopenharmony_ci 390bf215546Sopenharmony_ci/** 391bf215546Sopenharmony_ci * Generates the PDS vertex primary program for the dma's listed in the input 392bf215546Sopenharmony_ci * structure. Produces the constant map for the Vulkan driver based upon the 393bf215546Sopenharmony_ci * requirements of the instructions added to the program. 394bf215546Sopenharmony_ci * 395bf215546Sopenharmony_ci * PDS Data Layout 396bf215546Sopenharmony_ci * --------------- 397bf215546Sopenharmony_ci * 398bf215546Sopenharmony_ci * The PDS data is optimized for the DDMAD layout, with the data for those 399bf215546Sopenharmony_ci * instructions laid out first. The data required for other instructions is laid 400bf215546Sopenharmony_ci * out in the entries unused by the DDMADs. 401bf215546Sopenharmony_ci * 402bf215546Sopenharmony_ci * DDMAD layout 403bf215546Sopenharmony_ci * \verbatim 404bf215546Sopenharmony_ci * bank | index | usage 405bf215546Sopenharmony_ci * 0 | 0:1 | temps (current index)[-] 406bf215546Sopenharmony_ci * 2 | 2:3 | stride[32] 407bf215546Sopenharmony_ci * 1 | 4:5 | base address[64] 408bf215546Sopenharmony_ci * 3 | 6:7 | ctrl[64] 409bf215546Sopenharmony_ci * \endverbatim 410bf215546Sopenharmony_ci * 411bf215546Sopenharmony_ci * Each DMA whose stride > 0 requires one entry, laid out as above. We stride 412bf215546Sopenharmony_ci * over the banks to ensure that each ddmad reads each of its operands from a 413bf215546Sopenharmony_ci * different bank (i.e. remove bank clashes) 414bf215546Sopenharmony_ci * 415bf215546Sopenharmony_ci * Note: This is "wasting" const[0:1] and const[2], however these free 416bf215546Sopenharmony_ci * registers will be used by other, non-ddmad instructions. 417bf215546Sopenharmony_ci * 418bf215546Sopenharmony_ci * The const register usage is maintained in the au8ConstUsage array, the 419bf215546Sopenharmony_ci * DDMAD instructions, for example, will utilize the top 5 registers in each 420bf215546Sopenharmony_ci * block of 8 hence a 'usage mask' of 0xF8 (0b11111000). 421bf215546Sopenharmony_ci * 422bf215546Sopenharmony_ci * Constant Map 423bf215546Sopenharmony_ci * ------------ 424bf215546Sopenharmony_ci * 425bf215546Sopenharmony_ci * The constant map is built up as we add PDS instructions and passed back 426bf215546Sopenharmony_ci * for the driver to fill in the PDS data section with the correct parameters 427bf215546Sopenharmony_ci * for each draw call. 428bf215546Sopenharmony_ci * 429bf215546Sopenharmony_ci * \param input_program PDS Program description. 430bf215546Sopenharmony_ci * \param code Buffer to be filled in with the PDS program. If NULL is provided, 431bf215546Sopenharmony_ci * automatically switch to count-mode, preventing writes to 432bf215546Sopenharmony_ci * unallocated memory. 433bf215546Sopenharmony_ci * \param info PDS info structure filled in for the driver, contains the 434bf215546Sopenharmony_ci * constant map. 435bf215546Sopenharmony_ci * \param use_robust_vertex_fetch Do vertex fetches apply range checking. 436bf215546Sopenharmony_ci * \param dev_info pvr device information struct. 437bf215546Sopenharmony_ci */ 438bf215546Sopenharmony_civoid pvr_pds_generate_vertex_primary_program( 439bf215546Sopenharmony_ci struct pvr_pds_vertex_primary_program_input *input_program, 440bf215546Sopenharmony_ci uint32_t *code, 441bf215546Sopenharmony_ci struct pvr_pds_info *info, 442bf215546Sopenharmony_ci bool use_robust_vertex_fetch, 443bf215546Sopenharmony_ci const struct pvr_device_info *dev_info) 444bf215546Sopenharmony_ci{ 445bf215546Sopenharmony_ci struct pvr_pds_const_map_entry_write_state entry_write_state; 446bf215546Sopenharmony_ci struct pvr_const_map_entry_doutu_address *doutu_address_entry; 447bf215546Sopenharmony_ci 448bf215546Sopenharmony_ci uint32_t instruction = 0; /* index into code */ 449bf215546Sopenharmony_ci uint32_t index; /* index used for current attribute, either vertex or 450bf215546Sopenharmony_ci * instance. 451bf215546Sopenharmony_ci */ 452bf215546Sopenharmony_ci 453bf215546Sopenharmony_ci uint32_t total_dma_count = 0; 454bf215546Sopenharmony_ci uint32_t running_dma_count = 0; 455bf215546Sopenharmony_ci 456bf215546Sopenharmony_ci uint32_t write_instance_control = ~0; 457bf215546Sopenharmony_ci uint32_t write_vertex_control = ~0; 458bf215546Sopenharmony_ci uint32_t write_base_instance_control = ~0; 459bf215546Sopenharmony_ci uint32_t write_base_vertex_control = ~0; 460bf215546Sopenharmony_ci uint32_t pvr_write_draw_index_control = ~0; 461bf215546Sopenharmony_ci 462bf215546Sopenharmony_ci uint32_t ddmad_count = 0; 463bf215546Sopenharmony_ci uint32_t doutw_count = 0; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci uint32_t base_instance = 0; 466bf215546Sopenharmony_ci uint32_t base_vertex = 0; 467bf215546Sopenharmony_ci uint32_t draw_index = 0; 468bf215546Sopenharmony_ci 469bf215546Sopenharmony_ci uint8_t const_usage[PVR_MAX_VERTEX_ATTRIB_DMAS] = { 0 }; 470bf215546Sopenharmony_ci 471bf215546Sopenharmony_ci struct pvr_temp_usage temp_usage = { 0 }; 472bf215546Sopenharmony_ci 473bf215546Sopenharmony_ci uint32_t zero_temp = PVR_INVALID_TEMP; 474bf215546Sopenharmony_ci 475bf215546Sopenharmony_ci uint32_t max_index_temp = PVR_INVALID_TEMP; 476bf215546Sopenharmony_ci uint32_t current_index_temp = PVR_INVALID_TEMP; 477bf215546Sopenharmony_ci 478bf215546Sopenharmony_ci uint32_t index_id_temp = PVR_INVALID_TEMP; 479bf215546Sopenharmony_ci uint32_t base_instance_ID_temp = PVR_INVALID_TEMP; 480bf215546Sopenharmony_ci uint32_t instance_ID_temp = PVR_INVALID_TEMP; 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci /* Debug tracing of program flags. */ 483bf215546Sopenharmony_ci pvr_debug("pvr_pds_generate_vertex_primary_program"); 484bf215546Sopenharmony_ci pvr_debug("================================================="); 485bf215546Sopenharmony_ci pvr_debug_pds_flag(input_program->flags, 486bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_VERTEX_ID_REQUIRED); 487bf215546Sopenharmony_ci pvr_debug_pds_flag(input_program->flags, 488bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_INSTANCE_ID_REQUIRED); 489bf215546Sopenharmony_ci pvr_debug_pds_flag(input_program->flags, 490bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT); 491bf215546Sopenharmony_ci pvr_debug_pds_flag(input_program->flags, 492bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT); 493bf215546Sopenharmony_ci pvr_debug_pds_flag(input_program->flags, 494bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED); 495bf215546Sopenharmony_ci pvr_debug_pds_flag(input_program->flags, 496bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_VERTEX_REQUIRED); 497bf215546Sopenharmony_ci pvr_debug_pds_flag(input_program->flags, 498bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_DRAW_INDEX_REQUIRED); 499bf215546Sopenharmony_ci pvr_debug(" "); 500bf215546Sopenharmony_ci 501bf215546Sopenharmony_ci pvr_init_pds_const_map_entry_write_state(info, &entry_write_state); 502bf215546Sopenharmony_ci 503bf215546Sopenharmony_ci /* At a minimum we need 2 dwords for the DOUTU, but since we allocate in 504bf215546Sopenharmony_ci * blocks of 4 we can reserve dwords for the instance/vertex DOUTW. 505bf215546Sopenharmony_ci */ 506bf215546Sopenharmony_ci info->data_size_in_dwords = 4; 507bf215546Sopenharmony_ci 508bf215546Sopenharmony_ci /* Reserve 2 temps - these are automatically filled in by the VDM 509bf215546Sopenharmony_ci * 510bf215546Sopenharmony_ci * For instanced draw calls we manually increment the instance id by the 511bf215546Sopenharmony_ci * base-instance offset which is either provided as a constant, or in a 512bf215546Sopenharmony_ci * ptemp (for draw indirect) 513bf215546Sopenharmony_ci * 514bf215546Sopenharmony_ci * temp - contents 515bf215546Sopenharmony_ci * --------------- 516bf215546Sopenharmony_ci * 0 - index id (pre-filled) 517bf215546Sopenharmony_ci * 1 - base instance + instance id 518bf215546Sopenharmony_ci */ 519bf215546Sopenharmony_ci index_id_temp = pvr_get_temps(&temp_usage, RESERVE_32BIT, "VDM Index id"); 520bf215546Sopenharmony_ci instance_ID_temp = 521bf215546Sopenharmony_ci pvr_get_temps(&temp_usage, RESERVE_32BIT, "VDM Instance id"); 522bf215546Sopenharmony_ci 523bf215546Sopenharmony_ci /* Reserve the lowest 2 dwords for DOUTU. 524bf215546Sopenharmony_ci * [------XX] 525bf215546Sopenharmony_ci */ 526bf215546Sopenharmony_ci const_usage[0] = 0x03; 527bf215546Sopenharmony_ci 528bf215546Sopenharmony_ci /* Reserve consts for all the DDMAD's. */ 529bf215546Sopenharmony_ci for (uint32_t dma = 0; dma < input_program->dma_count; dma++) { 530bf215546Sopenharmony_ci /* Mark the consts required by this ddmad "in-use". 531bf215546Sopenharmony_ci * [XXXXX---] 532bf215546Sopenharmony_ci */ 533bf215546Sopenharmony_ci const_usage[ddmad_count++] |= 0xf8; 534bf215546Sopenharmony_ci } 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci /* Start off by assuming we can fit everything in the 8 dwords/ddmad 537bf215546Sopenharmony_ci * footprint, if any DOUTD/DOUTW falls outside we will increase this 538bf215546Sopenharmony_ci * counter. 539bf215546Sopenharmony_ci */ 540bf215546Sopenharmony_ci if (ddmad_count) 541bf215546Sopenharmony_ci info->data_size_in_dwords = PVR_PDS_DDMAD_NUM_CONSTS * ddmad_count; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_VERTEX_ID_REQUIRED) { 544bf215546Sopenharmony_ci doutw_count++; 545bf215546Sopenharmony_ci write_vertex_control = 546bf215546Sopenharmony_ci pvr_find_constant(const_usage, RESERVE_32BIT, "Vertex id DOUTW Ctrl"); 547bf215546Sopenharmony_ci } 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_INSTANCE_ID_REQUIRED) { 550bf215546Sopenharmony_ci doutw_count++; 551bf215546Sopenharmony_ci write_instance_control = pvr_find_constant(const_usage, 552bf215546Sopenharmony_ci RESERVE_32BIT, 553bf215546Sopenharmony_ci "Instance id DOUTW Ctrl"); 554bf215546Sopenharmony_ci } 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED) { 557bf215546Sopenharmony_ci doutw_count++; 558bf215546Sopenharmony_ci write_base_instance_control = 559bf215546Sopenharmony_ci pvr_find_constant(const_usage, 560bf215546Sopenharmony_ci RESERVE_32BIT, 561bf215546Sopenharmony_ci "Base Instance DOUTW Ctrl"); 562bf215546Sopenharmony_ci } 563bf215546Sopenharmony_ci 564bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_VERTEX_REQUIRED) { 565bf215546Sopenharmony_ci doutw_count++; 566bf215546Sopenharmony_ci write_base_vertex_control = pvr_find_constant(const_usage, 567bf215546Sopenharmony_ci RESERVE_32BIT, 568bf215546Sopenharmony_ci "Base Vertex DOUTW Ctrl"); 569bf215546Sopenharmony_ci 570bf215546Sopenharmony_ci /* Load base vertex from constant for non-indirect variants. */ 571bf215546Sopenharmony_ci if ((input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) == 572bf215546Sopenharmony_ci 0) { 573bf215546Sopenharmony_ci struct pvr_const_map_entry_base_vertex *psBaseVertexEntry = 574bf215546Sopenharmony_ci (struct pvr_const_map_entry_base_vertex *)entry_write_state.entry; 575bf215546Sopenharmony_ci 576bf215546Sopenharmony_ci base_vertex = 577bf215546Sopenharmony_ci pvr_find_constant(const_usage, RESERVE_32BIT, "base_vertex"); 578bf215546Sopenharmony_ci 579bf215546Sopenharmony_ci psBaseVertexEntry = 580bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 581bf215546Sopenharmony_ci sizeof(*psBaseVertexEntry)); 582bf215546Sopenharmony_ci psBaseVertexEntry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_VERTEX; 583bf215546Sopenharmony_ci psBaseVertexEntry->const_offset = base_vertex; 584bf215546Sopenharmony_ci } 585bf215546Sopenharmony_ci } 586bf215546Sopenharmony_ci 587bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDEX_REQUIRED) { 588bf215546Sopenharmony_ci doutw_count++; 589bf215546Sopenharmony_ci pvr_write_draw_index_control = 590bf215546Sopenharmony_ci pvr_find_constant(const_usage, RESERVE_32BIT, "Draw Index DOUTW Ctrl"); 591bf215546Sopenharmony_ci 592bf215546Sopenharmony_ci /* Set draw index to 0 for non-indirect variants. */ 593bf215546Sopenharmony_ci if ((input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) == 594bf215546Sopenharmony_ci 0) { 595bf215546Sopenharmony_ci struct pvr_const_map_entry_literal32 *literal_entry; 596bf215546Sopenharmony_ci 597bf215546Sopenharmony_ci draw_index = 598bf215546Sopenharmony_ci pvr_find_constant(const_usage, RESERVE_32BIT, "draw_index"); 599bf215546Sopenharmony_ci 600bf215546Sopenharmony_ci literal_entry = 601bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 602bf215546Sopenharmony_ci sizeof(*literal_entry)); 603bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 604bf215546Sopenharmony_ci literal_entry->const_offset = draw_index; 605bf215546Sopenharmony_ci literal_entry->literal_value = 0; 606bf215546Sopenharmony_ci } 607bf215546Sopenharmony_ci } 608bf215546Sopenharmony_ci 609bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) { 610bf215546Sopenharmony_ci /* Load absolute instance id into uiInstanceIdTemp. */ 611bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 612bf215546Sopenharmony_ci code, 613bf215546Sopenharmony_ci instruction, 614bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 615bf215546Sopenharmony_ci /* cc */ 0, 616bf215546Sopenharmony_ci /* alum */ 0, 617bf215546Sopenharmony_ci /* sna */ 0, 618bf215546Sopenharmony_ci /* src0 */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP), 619bf215546Sopenharmony_ci /* src1 */ R32_T(instance_ID_temp), 620bf215546Sopenharmony_ci /* dst */ R32TP_T(instance_ID_temp))); 621bf215546Sopenharmony_ci } else if (input_program->flags & 622bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) { 623bf215546Sopenharmony_ci struct pvr_const_map_entry_base_instance *base_instance_entry = 624bf215546Sopenharmony_ci (struct pvr_const_map_entry_base_instance *)entry_write_state.entry; 625bf215546Sopenharmony_ci 626bf215546Sopenharmony_ci base_instance = 627bf215546Sopenharmony_ci pvr_find_constant(const_usage, RESERVE_32BIT, "base_instance"); 628bf215546Sopenharmony_ci 629bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 630bf215546Sopenharmony_ci instruction, 631bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 632bf215546Sopenharmony_ci /* cc */ 0, 633bf215546Sopenharmony_ci /* alum */ 0, 634bf215546Sopenharmony_ci /* sna */ 0, 635bf215546Sopenharmony_ci /* src0 */ R32_C(base_instance), 636bf215546Sopenharmony_ci /* src1 */ R32_T(instance_ID_temp), 637bf215546Sopenharmony_ci /* dst */ R32TP_T(instance_ID_temp))); 638bf215546Sopenharmony_ci 639bf215546Sopenharmony_ci base_instance_entry = 640bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 641bf215546Sopenharmony_ci sizeof(*base_instance_entry)); 642bf215546Sopenharmony_ci base_instance_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_INSTANCE; 643bf215546Sopenharmony_ci base_instance_entry->const_offset = base_instance; 644bf215546Sopenharmony_ci } else if (input_program->flags & 645bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED) { 646bf215546Sopenharmony_ci struct pvr_const_map_entry_base_instance *base_instance_entry = 647bf215546Sopenharmony_ci (struct pvr_const_map_entry_base_instance *)entry_write_state.entry; 648bf215546Sopenharmony_ci 649bf215546Sopenharmony_ci base_instance = pvr_find_constant(const_usage, 650bf215546Sopenharmony_ci RESERVE_32BIT, 651bf215546Sopenharmony_ci "base_instance (Driver Const)"); 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci /* Base instance provided by the driver. */ 654bf215546Sopenharmony_ci base_instance_entry = 655bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 656bf215546Sopenharmony_ci sizeof(*base_instance_entry)); 657bf215546Sopenharmony_ci base_instance_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_INSTANCE; 658bf215546Sopenharmony_ci base_instance_entry->const_offset = base_instance; 659bf215546Sopenharmony_ci } 660bf215546Sopenharmony_ci 661bf215546Sopenharmony_ci total_dma_count = ddmad_count; 662bf215546Sopenharmony_ci 663bf215546Sopenharmony_ci total_dma_count += doutw_count; 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_ci if (use_robust_vertex_fetch) { 666bf215546Sopenharmony_ci pvr_debug_pds_note("RobustBufferVertexFetch Initialization"); 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, pds_ddmadt)) { 669bf215546Sopenharmony_ci zero_temp = pvr_get_temps(&temp_usage, RESERVE_32BIT, "zero_temp"); 670bf215546Sopenharmony_ci 671bf215546Sopenharmony_ci /* Load 0 into instance_ID_temp. */ 672bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 673bf215546Sopenharmony_ci instruction, 674bf215546Sopenharmony_ci pvr_pds_inst_encode_limm(0, /* cc */ 675bf215546Sopenharmony_ci zero_temp, /* SRC1 */ 676bf215546Sopenharmony_ci 0, /* SRC0 */ 677bf215546Sopenharmony_ci 0 /* GR */ 678bf215546Sopenharmony_ci )); 679bf215546Sopenharmony_ci } else { 680bf215546Sopenharmony_ci zero_temp = pvr_get_temps(&temp_usage, RESERVE_64BIT, "zero_temp"); 681bf215546Sopenharmony_ci 682bf215546Sopenharmony_ci max_index_temp = 683bf215546Sopenharmony_ci pvr_get_temps(&temp_usage, RESERVE_64BIT, "uMaxIndex"); 684bf215546Sopenharmony_ci current_index_temp = 685bf215546Sopenharmony_ci pvr_get_temps(&temp_usage, RESERVE_64BIT, "uCurrentIndex"); 686bf215546Sopenharmony_ci 687bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 688bf215546Sopenharmony_ci instruction, 689bf215546Sopenharmony_ci pvr_pds_inst_encode_stflp64( 690bf215546Sopenharmony_ci 0, /* cc */ 691bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_LOP_XOR, /* LOP */ 692bf215546Sopenharmony_ci 1, /* IM */ 693bf215546Sopenharmony_ci R64TP_T(zero_temp >> 1), /* SRC0 (REGS64TP) 694bf215546Sopenharmony_ci */ 695bf215546Sopenharmony_ci R64TP_T(zero_temp >> 1), /* SRC1 (REGS64TP) 696bf215546Sopenharmony_ci */ 697bf215546Sopenharmony_ci 0, /* SRC2 (REGS32) */ 698bf215546Sopenharmony_ci R64TP_T(zero_temp >> 1) /* DST (REG64TP) */ 699bf215546Sopenharmony_ci )); 700bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 701bf215546Sopenharmony_ci instruction, 702bf215546Sopenharmony_ci pvr_pds_inst_encode_stflp64( 703bf215546Sopenharmony_ci 0, /* cc */ 704bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */ 705bf215546Sopenharmony_ci 1, /* IM */ 706bf215546Sopenharmony_ci R64TP_T(zero_temp >> 1), /* SRC0 (REGS64TP) 707bf215546Sopenharmony_ci */ 708bf215546Sopenharmony_ci 0, /* SRC1 (REGS64TP) */ 709bf215546Sopenharmony_ci 0, /* SRC2 (REGS32) */ 710bf215546Sopenharmony_ci R64TP_T(current_index_temp >> 1) /* DST */ 711bf215546Sopenharmony_ci /* (REG64TP) */ 712bf215546Sopenharmony_ci )); 713bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 714bf215546Sopenharmony_ci instruction, 715bf215546Sopenharmony_ci pvr_pds_inst_encode_stflp64( 716bf215546Sopenharmony_ci 0, /* cc */ 717bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */ 718bf215546Sopenharmony_ci 1, /* IM */ 719bf215546Sopenharmony_ci R64TP_T(zero_temp >> 1), /* SRC0 (REGS64TP) 720bf215546Sopenharmony_ci */ 721bf215546Sopenharmony_ci 0, /* SRC1 (REGS64TP) */ 722bf215546Sopenharmony_ci 0, /* SRC2 (REGS32) */ 723bf215546Sopenharmony_ci R64TP_T(max_index_temp >> 1) /* DST */ 724bf215546Sopenharmony_ci /* (REG64TP) */ 725bf215546Sopenharmony_ci )); 726bf215546Sopenharmony_ci } 727bf215546Sopenharmony_ci } 728bf215546Sopenharmony_ci 729bf215546Sopenharmony_ci if (input_program->dma_count && use_robust_vertex_fetch) { 730bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 731bf215546Sopenharmony_ci code, 732bf215546Sopenharmony_ci instruction, 733bf215546Sopenharmony_ci pvr_pds_inst_encode_bra(PVR_ROGUE_PDSINST_PREDICATE_KEEP, /* SRCC */ 734bf215546Sopenharmony_ci 0, /* Neg */ 735bf215546Sopenharmony_ci PVR_HAS_FEATURE(dev_info, pds_ddmadt) 736bf215546Sopenharmony_ci ? PVR_ROGUE_PDSINST_PREDICATE_OOB 737bf215546Sopenharmony_ci : PVR_ROGUE_PDSINST_PREDICATE_P0, /* SETC */ 738bf215546Sopenharmony_ci 1 /* Addr */ 739bf215546Sopenharmony_ci )); 740bf215546Sopenharmony_ci } 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci for (uint32_t dma = 0; dma < input_program->dma_count; dma++) { 743bf215546Sopenharmony_ci uint32_t const_base = dma * PVR_PDS_DDMAD_NUM_CONSTS; 744bf215546Sopenharmony_ci uint32_t control_word; 745bf215546Sopenharmony_ci struct pvr_const_map_entry_literal32 *literal_entry; 746bf215546Sopenharmony_ci 747bf215546Sopenharmony_ci struct pvr_pds_vertex_dma *vertex_dma = &input_program->dma_list[dma]; 748bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 749bf215546Sopenharmony_ci 750bf215546Sopenharmony_ci pvr_debug_pds_note("Vertex Attribute DMA %d (last=%d)", dma, last_DMA); 751bf215546Sopenharmony_ci 752bf215546Sopenharmony_ci /* The id we use to index into this dma. */ 753bf215546Sopenharmony_ci if (vertex_dma->flags & PVR_PDS_VERTEX_DMA_FLAGS_INSTANCE_RATE) { 754bf215546Sopenharmony_ci pvr_debug_pds_note("Instance Rate (divisor = %d)", 755bf215546Sopenharmony_ci vertex_dma->divisor); 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci /* 4 - madd 0 - needs to be 64-bit aligned 758bf215546Sopenharmony_ci * 5 - madd 1 759bf215546Sopenharmony_ci */ 760bf215546Sopenharmony_ci if (vertex_dma->divisor > 1) { 761bf215546Sopenharmony_ci const uint32_t adjusted_instance_ID_temp = 762bf215546Sopenharmony_ci pvr_get_temps(&temp_usage, 763bf215546Sopenharmony_ci RESERVE_64BIT, 764bf215546Sopenharmony_ci "adjusted_instance_ID_temp"); 765bf215546Sopenharmony_ci const uint32_t MADD_temp = 766bf215546Sopenharmony_ci pvr_get_temps(&temp_usage, RESERVE_64BIT, "MADD_temp"); 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci /* 1. Remove base instance value from temp 1 to get instance id 769bf215546Sopenharmony_ci * 2. Divide the instance id by the divisor - Iout = (Iin * 770bf215546Sopenharmony_ci * Multiplier) >> (shift+31) 771bf215546Sopenharmony_ci * 3. Add the base instance back on. 772bf215546Sopenharmony_ci * 773bf215546Sopenharmony_ci * Need two zero temps for the add part of the later MAD. 774bf215546Sopenharmony_ci */ 775bf215546Sopenharmony_ci 776bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 777bf215546Sopenharmony_ci instruction, 778bf215546Sopenharmony_ci pvr_pds_inst_encode_add64( 779bf215546Sopenharmony_ci /* cc */ 0, 780bf215546Sopenharmony_ci /* alum */ 0, 781bf215546Sopenharmony_ci /* sna */ 1, 782bf215546Sopenharmony_ci /* src0 */ R64_T(MADD_temp >> 1), 783bf215546Sopenharmony_ci /* src1 */ R64_T(MADD_temp >> 1), 784bf215546Sopenharmony_ci /* dst */ R64TP_T(MADD_temp >> 1))); 785bf215546Sopenharmony_ci 786bf215546Sopenharmony_ci if (input_program->flags & 787bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) { 788bf215546Sopenharmony_ci /* Subtract base instance from temp 1, put into 789bf215546Sopenharmony_ci * adjusted_instance_ID_temp. 790bf215546Sopenharmony_ci */ 791bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 792bf215546Sopenharmony_ci code, 793bf215546Sopenharmony_ci instruction, 794bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 795bf215546Sopenharmony_ci /* cc */ 0, 796bf215546Sopenharmony_ci /* alum */ 0, 797bf215546Sopenharmony_ci /* sna */ 1, 798bf215546Sopenharmony_ci /* src0 */ R32_T(instance_ID_temp), 799bf215546Sopenharmony_ci /* src1 */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP), 800bf215546Sopenharmony_ci /* dst */ R32TP_T(adjusted_instance_ID_temp))); 801bf215546Sopenharmony_ci } else if (input_program->flags & 802bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) { 803bf215546Sopenharmony_ci /* Subtract base instance from temp 1, put into 804bf215546Sopenharmony_ci * adjusted_instance_ID_temp. 805bf215546Sopenharmony_ci */ 806bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 807bf215546Sopenharmony_ci code, 808bf215546Sopenharmony_ci instruction, 809bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 810bf215546Sopenharmony_ci /* cc */ 0, 811bf215546Sopenharmony_ci /* alum */ 0, 812bf215546Sopenharmony_ci /* sna */ 1, 813bf215546Sopenharmony_ci /* src0 */ R32_T(instance_ID_temp), 814bf215546Sopenharmony_ci /* src1 */ R32_C(base_instance), 815bf215546Sopenharmony_ci /* dst */ R32TP_T(adjusted_instance_ID_temp))); 816bf215546Sopenharmony_ci } else { 817bf215546Sopenharmony_ci /* Copy instance from temp 1 to adjusted_instance_ID_temp. 818bf215546Sopenharmony_ci */ 819bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 820bf215546Sopenharmony_ci code, 821bf215546Sopenharmony_ci instruction, 822bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 823bf215546Sopenharmony_ci /* cc */ 0, 824bf215546Sopenharmony_ci /* alum */ 0, 825bf215546Sopenharmony_ci /* sna */ 0, 826bf215546Sopenharmony_ci /* src0 */ R32_T(instance_ID_temp), 827bf215546Sopenharmony_ci /* src1 */ R32_T(MADD_temp), /* MADD_temp is set 828bf215546Sopenharmony_ci * to 0 at this point. 829bf215546Sopenharmony_ci */ 830bf215546Sopenharmony_ci /* dst */ R32TP_T(adjusted_instance_ID_temp))); 831bf215546Sopenharmony_ci } 832bf215546Sopenharmony_ci 833bf215546Sopenharmony_ci /* shift = the bit of the next highest power of two. */ 834bf215546Sopenharmony_ci uint32_t shift_unsigned = 835bf215546Sopenharmony_ci (31 - __builtin_clz(vertex_dma->divisor - 1)) + 1; 836bf215546Sopenharmony_ci int32_t shift = (int32_t)shift_unsigned; 837bf215546Sopenharmony_ci uint32_t shift_2s_comp; 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci pvr_debug_pds_note( 840bf215546Sopenharmony_ci "Perform instance rate divide (as integer multiply and rshift)"); 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_ci const uint32_t multipier_constant = 843bf215546Sopenharmony_ci pvr_find_constant(const_usage, 844bf215546Sopenharmony_ci RESERVE_32BIT, 845bf215546Sopenharmony_ci "MultiplierConstant (for InstanceDivisor)"); 846bf215546Sopenharmony_ci 847bf215546Sopenharmony_ci /* multiplier = ( 2^(shift + 31) + (divisor - 1) ) / divisor, 848bf215546Sopenharmony_ci note: the division above is integer division. */ 849bf215546Sopenharmony_ci uint64_t multipier64 = 850bf215546Sopenharmony_ci (uint64_t)((((uint64_t)1 << ((uint64_t)shift_unsigned + 31)) + 851bf215546Sopenharmony_ci ((uint64_t)vertex_dma->divisor - (uint64_t)1)) / 852bf215546Sopenharmony_ci (uint64_t)vertex_dma->divisor); 853bf215546Sopenharmony_ci uint32_t multiplier = (uint32_t)multipier64; 854bf215546Sopenharmony_ci 855bf215546Sopenharmony_ci pvr_debug_pds_note(" - Value of MultiplierConstant = %u", 856bf215546Sopenharmony_ci multiplier); 857bf215546Sopenharmony_ci pvr_debug_pds_note(" - Value of Shift = %d", shift); 858bf215546Sopenharmony_ci 859bf215546Sopenharmony_ci literal_entry = 860bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 861bf215546Sopenharmony_ci sizeof(*literal_entry)); 862bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 863bf215546Sopenharmony_ci literal_entry->const_offset = multipier_constant; 864bf215546Sopenharmony_ci literal_entry->literal_value = multiplier; 865bf215546Sopenharmony_ci 866bf215546Sopenharmony_ci /* (Iin * Multiplier) */ 867bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 868bf215546Sopenharmony_ci code, 869bf215546Sopenharmony_ci instruction, 870bf215546Sopenharmony_ci pvr_rogue_inst_encode_mad(0, /* Sign of add is positive */ 871bf215546Sopenharmony_ci 0, /* Unsigned ALU mode */ 872bf215546Sopenharmony_ci 0, /* Unconditional */ 873bf215546Sopenharmony_ci R32_C(multipier_constant), 874bf215546Sopenharmony_ci R32_T(adjusted_instance_ID_temp), 875bf215546Sopenharmony_ci R64_T(MADD_temp / 2), 876bf215546Sopenharmony_ci R64TP_T(MADD_temp / 2))); 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci /* >> (shift + 31) */ 879bf215546Sopenharmony_ci shift += 31; 880bf215546Sopenharmony_ci shift *= -1; 881bf215546Sopenharmony_ci 882bf215546Sopenharmony_ci if (shift < -31) { 883bf215546Sopenharmony_ci /* >> (31) */ 884bf215546Sopenharmony_ci shift_2s_comp = 0xFFFE1; 885bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 886bf215546Sopenharmony_ci instruction, 887bf215546Sopenharmony_ci pvr_pds_inst_encode_stflp64( 888bf215546Sopenharmony_ci /* cc */ 0, 889bf215546Sopenharmony_ci /* LOP */ PVR_ROGUE_PDSINST_LOP_NONE, 890bf215546Sopenharmony_ci /* IM */ 1, /* enable immediate */ 891bf215546Sopenharmony_ci /* SRC0 */ R64_T(MADD_temp / 2), 892bf215546Sopenharmony_ci /* SRC1 */ 0, /* This won't be used 893bf215546Sopenharmony_ci in a shift 894bf215546Sopenharmony_ci operation. */ 895bf215546Sopenharmony_ci /* SRC2 (Shift) */ shift_2s_comp, 896bf215546Sopenharmony_ci /* DST */ R64TP_T(MADD_temp / 2))); 897bf215546Sopenharmony_ci shift += 31; 898bf215546Sopenharmony_ci } 899bf215546Sopenharmony_ci 900bf215546Sopenharmony_ci /* >> (shift + 31) */ 901bf215546Sopenharmony_ci shift_2s_comp = *((uint32_t *)&shift); 902bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 903bf215546Sopenharmony_ci instruction, 904bf215546Sopenharmony_ci pvr_pds_inst_encode_stflp64( 905bf215546Sopenharmony_ci /* cc */ 0, 906bf215546Sopenharmony_ci /* LOP */ PVR_ROGUE_PDSINST_LOP_NONE, 907bf215546Sopenharmony_ci /* IM */ 1, /* enable immediate */ 908bf215546Sopenharmony_ci /* SRC0 */ R64_T(MADD_temp / 2), 909bf215546Sopenharmony_ci /* SRC1 */ 0, /* This won't be used 910bf215546Sopenharmony_ci * in a shift 911bf215546Sopenharmony_ci * operation. */ 912bf215546Sopenharmony_ci /* SRC2 (Shift) */ shift_2s_comp, 913bf215546Sopenharmony_ci /* DST */ R64TP_T(MADD_temp / 2))); 914bf215546Sopenharmony_ci 915bf215546Sopenharmony_ci if (input_program->flags & 916bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) { 917bf215546Sopenharmony_ci /* Add base instance. */ 918bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 919bf215546Sopenharmony_ci code, 920bf215546Sopenharmony_ci instruction, 921bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 922bf215546Sopenharmony_ci /* cc */ 0, 923bf215546Sopenharmony_ci /* alum */ 0, 924bf215546Sopenharmony_ci /* sna */ 0, 925bf215546Sopenharmony_ci /* src0 */ R32_T(MADD_temp), 926bf215546Sopenharmony_ci /* src1 */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP), 927bf215546Sopenharmony_ci /* dst */ R32TP_T(MADD_temp))); 928bf215546Sopenharmony_ci } else if (input_program->flags & 929bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) { 930bf215546Sopenharmony_ci /* Add base instance. */ 931bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 932bf215546Sopenharmony_ci instruction, 933bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 934bf215546Sopenharmony_ci /* cc */ 0, 935bf215546Sopenharmony_ci /* alum */ 0, 936bf215546Sopenharmony_ci /* sna */ 0, 937bf215546Sopenharmony_ci /* src0 */ R32_T(MADD_temp), 938bf215546Sopenharmony_ci /* src1 */ R32_C(base_instance), 939bf215546Sopenharmony_ci /* dst */ R32TP_T(MADD_temp))); 940bf215546Sopenharmony_ci } 941bf215546Sopenharmony_ci 942bf215546Sopenharmony_ci pvr_debug_pds_note( 943bf215546Sopenharmony_ci "DMA Vertex Index will be sourced from 'MADD_temp'"); 944bf215546Sopenharmony_ci index = MADD_temp; 945bf215546Sopenharmony_ci } else if (vertex_dma->divisor == 0) { 946bf215546Sopenharmony_ci if (base_instance_ID_temp == PVR_INVALID_TEMP) { 947bf215546Sopenharmony_ci base_instance_ID_temp = pvr_get_temps(&temp_usage, 948bf215546Sopenharmony_ci RESERVE_32BIT, 949bf215546Sopenharmony_ci "uBaseInstanceIDTemp"); 950bf215546Sopenharmony_ci } 951bf215546Sopenharmony_ci 952bf215546Sopenharmony_ci /* Load 0 into instance_ID_temp. */ 953bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 954bf215546Sopenharmony_ci instruction, 955bf215546Sopenharmony_ci pvr_pds_inst_encode_limm( 956bf215546Sopenharmony_ci /* cc */ 0, 957bf215546Sopenharmony_ci /* src1 */ base_instance_ID_temp, 958bf215546Sopenharmony_ci /* src0 */ 0, 959bf215546Sopenharmony_ci /* gr */ 0)); 960bf215546Sopenharmony_ci 961bf215546Sopenharmony_ci if (input_program->flags & 962bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) { 963bf215546Sopenharmony_ci /* Add base instance. */ 964bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 965bf215546Sopenharmony_ci code, 966bf215546Sopenharmony_ci instruction, 967bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 968bf215546Sopenharmony_ci /* cc */ 0, 969bf215546Sopenharmony_ci /* alum */ 0, 970bf215546Sopenharmony_ci /* sna */ 0, 971bf215546Sopenharmony_ci /* src0 */ R32_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP), 972bf215546Sopenharmony_ci /* src1 */ R32_T(base_instance_ID_temp), 973bf215546Sopenharmony_ci /* dst */ R32TP_T(base_instance_ID_temp))); 974bf215546Sopenharmony_ci 975bf215546Sopenharmony_ci } else if (input_program->flags & 976bf215546Sopenharmony_ci PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_VARIANT) { 977bf215546Sopenharmony_ci /* Add base instance. */ 978bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 979bf215546Sopenharmony_ci code, 980bf215546Sopenharmony_ci instruction, 981bf215546Sopenharmony_ci pvr_pds_inst_encode_add32( 982bf215546Sopenharmony_ci /* cc */ 0, 983bf215546Sopenharmony_ci /* alum */ 0, 984bf215546Sopenharmony_ci /* sna */ 0, 985bf215546Sopenharmony_ci /* src0 */ R32_C(base_instance), 986bf215546Sopenharmony_ci /* src1 */ R32_T(base_instance_ID_temp), 987bf215546Sopenharmony_ci /* dst */ R32TP_T(base_instance_ID_temp))); 988bf215546Sopenharmony_ci } 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci pvr_debug_pds_note( 991bf215546Sopenharmony_ci "DMA Vertex Index will be sourced from 'uBaseInstanceIdTemp'"); 992bf215546Sopenharmony_ci index = base_instance_ID_temp; 993bf215546Sopenharmony_ci } else { 994bf215546Sopenharmony_ci pvr_debug_pds_note( 995bf215546Sopenharmony_ci "DMA Vertex Index will be sourced from 'uInstanceIdTemp'"); 996bf215546Sopenharmony_ci index = instance_ID_temp; 997bf215546Sopenharmony_ci } 998bf215546Sopenharmony_ci } else { 999bf215546Sopenharmony_ci pvr_debug_pds_note( 1000bf215546Sopenharmony_ci "DMA Vertex Index will be sourced from 'uIndexIdTemp'"); 1001bf215546Sopenharmony_ci index = index_id_temp; 1002bf215546Sopenharmony_ci } 1003bf215546Sopenharmony_ci 1004bf215546Sopenharmony_ci /* DDMAD Const Usage [__XX_---] */ 1005bf215546Sopenharmony_ci pvr_write_pds_const_map_entry_vertex_attribute_address( 1006bf215546Sopenharmony_ci &entry_write_state, 1007bf215546Sopenharmony_ci vertex_dma, 1008bf215546Sopenharmony_ci const_base + 4, 1009bf215546Sopenharmony_ci use_robust_vertex_fetch); 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_ci /* DDMAD Const Usage [__XXX---] */ 1012bf215546Sopenharmony_ci literal_entry = 1013bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1014bf215546Sopenharmony_ci sizeof(*literal_entry)); 1015bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 1016bf215546Sopenharmony_ci literal_entry->const_offset = const_base + 3; 1017bf215546Sopenharmony_ci literal_entry->literal_value = vertex_dma->stride; 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_ci control_word = vertex_dma->size_in_dwords 1020bf215546Sopenharmony_ci << PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_BSIZE_SHIFT; 1021bf215546Sopenharmony_ci control_word |= vertex_dma->destination 1022bf215546Sopenharmony_ci << PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_AO_SHIFT; 1023bf215546Sopenharmony_ci control_word |= (PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_DEST_UNIFIED_STORE | 1024bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_CMODE_CACHED); 1025bf215546Sopenharmony_ci 1026bf215546Sopenharmony_ci /* DDMADT instructions will do a dummy doutd when OOB if 1027bf215546Sopenharmony_ci * PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_LAST_EN is set but as the driver 1028bf215546Sopenharmony_ci * would need to do another doutd after an OOB DDMADT to provide the 'in 1029bf215546Sopenharmony_ci * bounds' data the DDMADT can't be set as LAST. 1030bf215546Sopenharmony_ci * 1031bf215546Sopenharmony_ci * This requires us to include a final dummy DDMAD.LAST instruction. 1032bf215546Sopenharmony_ci * 1033bf215546Sopenharmony_ci * Pseudocode taken from SeriesXE2017.PDS Instruction Controller 1034bf215546Sopenharmony_ci * Specification.doc 1035bf215546Sopenharmony_ci * 1036bf215546Sopenharmony_ci * DDMAD src0,src1,src2,src3 1037bf215546Sopenharmony_ci * 1038bf215546Sopenharmony_ci * calculated_source_address := src0*src1+src2 1039bf215546Sopenharmony_ci * base_address := src2 1040bf215546Sopenharmony_ci * dma_parameters := src3[31:0] 1041bf215546Sopenharmony_ci * buffer_size := src3[63:33] 1042bf215546Sopenharmony_ci * test := src3[32] 1043bf215546Sopenharmony_ci * 1044bf215546Sopenharmony_ci * if (test == 1) { 1045bf215546Sopenharmony_ci * // DDMAD(T) 1046bf215546Sopenharmony_ci * if (calculated_source_address[39:0] + (burst_size<<2) <= 1047bf215546Sopenharmony_ci * base_address[39:0] + buffer_size) { 1048bf215546Sopenharmony_ci * OOB := 0 1049bf215546Sopenharmony_ci * DOUTD calculated_source_address,dma_paramters 1050bf215546Sopenharmony_ci * } else { 1051bf215546Sopenharmony_ci * OOB := 1 1052bf215546Sopenharmony_ci * if (last_instance == 1) { 1053bf215546Sopenharmony_ci * dma_parameters[BURST_SIZE] := 0 1054bf215546Sopenharmony_ci * DOUTD calculated_source_address,dma_paramters 1055bf215546Sopenharmony_ci * } 1056bf215546Sopenharmony_ci * } 1057bf215546Sopenharmony_ci * } else { 1058bf215546Sopenharmony_ci * // DDMAD 1059bf215546Sopenharmony_ci * DOUTD calculated_source_address,dma_paramters 1060bf215546Sopenharmony_ci * } 1061bf215546Sopenharmony_ci */ 1062bf215546Sopenharmony_ci 1063bf215546Sopenharmony_ci if (last_DMA && (!PVR_HAS_FEATURE(dev_info, pds_ddmadt) || 1064bf215546Sopenharmony_ci !use_robust_vertex_fetch)) { 1065bf215546Sopenharmony_ci pvr_debug_pds_note("LAST DDMAD"); 1066bf215546Sopenharmony_ci control_word |= PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_LAST_EN; 1067bf215546Sopenharmony_ci } 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_ci /* DDMAD Const Usage [_XXXX---] */ 1070bf215546Sopenharmony_ci literal_entry = 1071bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1072bf215546Sopenharmony_ci sizeof(*literal_entry)); 1073bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 1074bf215546Sopenharmony_ci literal_entry->const_offset = (const_base + 6); 1075bf215546Sopenharmony_ci literal_entry->literal_value = control_word; 1076bf215546Sopenharmony_ci 1077bf215546Sopenharmony_ci if (PVR_HAS_FEATURE(dev_info, pds_ddmadt)) { 1078bf215546Sopenharmony_ci /* DDMAD Const Usage [XXXXX---] 1079bf215546Sopenharmony_ci * With DDMADT an extra 32bits of SRC3 contains the information for 1080bf215546Sopenharmony_ci * performing out-of-bounds tests on the DMA. 1081bf215546Sopenharmony_ci */ 1082bf215546Sopenharmony_ci 1083bf215546Sopenharmony_ci if (use_robust_vertex_fetch) { 1084bf215546Sopenharmony_ci struct pvr_pds_const_map_entry_vertex_attr_ddmadt_oob_buffer_size 1085bf215546Sopenharmony_ci *obb_buffer_size; 1086bf215546Sopenharmony_ci obb_buffer_size = 1087bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1088bf215546Sopenharmony_ci sizeof(*obb_buffer_size)); 1089bf215546Sopenharmony_ci 1090bf215546Sopenharmony_ci obb_buffer_size->type = 1091bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTR_DDMADT_OOB_BUFFER_SIZE; 1092bf215546Sopenharmony_ci obb_buffer_size->const_offset = const_base + 7; 1093bf215546Sopenharmony_ci obb_buffer_size->binding_index = vertex_dma->binding_index; 1094bf215546Sopenharmony_ci } else { 1095bf215546Sopenharmony_ci literal_entry = 1096bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1097bf215546Sopenharmony_ci sizeof(*literal_entry)); 1098bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 1099bf215546Sopenharmony_ci literal_entry->const_offset = const_base + 7; 1100bf215546Sopenharmony_ci literal_entry->literal_value = 0; 1101bf215546Sopenharmony_ci } 1102bf215546Sopenharmony_ci 1103bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1104bf215546Sopenharmony_ci code, 1105bf215546Sopenharmony_ci instruction, 1106bf215546Sopenharmony_ci pvr_pds_inst_encode_ddmad(0, /* cc */ 1107bf215546Sopenharmony_ci 0, /* END */ 1108bf215546Sopenharmony_ci R32_C(const_base + 3), /* SRC0 (REGS32) */ 1109bf215546Sopenharmony_ci index, /* SRC1 (REGS32T) */ 1110bf215546Sopenharmony_ci R64_C((const_base + 4) >> 1), /* SRC2 1111bf215546Sopenharmony_ci * (REGS64) 1112bf215546Sopenharmony_ci */ 1113bf215546Sopenharmony_ci R64_C((const_base + 6) >> 1) /* SRC3 1114bf215546Sopenharmony_ci * (REGS64C) 1115bf215546Sopenharmony_ci */ 1116bf215546Sopenharmony_ci )); 1117bf215546Sopenharmony_ci 1118bf215546Sopenharmony_ci if (use_robust_vertex_fetch) { 1119bf215546Sopenharmony_ci /* If not out of bounds, skip next DDMAD instructions. */ 1120bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 1121bf215546Sopenharmony_ci instruction, 1122bf215546Sopenharmony_ci pvr_pds_inst_encode_ddmad( 1123bf215546Sopenharmony_ci 1, /* cc */ 1124bf215546Sopenharmony_ci 0, /* END */ 1125bf215546Sopenharmony_ci R32_C(const_base + 3), /* SRC0 (REGS32) */ 1126bf215546Sopenharmony_ci R32_T(zero_temp), /* SRC1 (REGS32T) */ 1127bf215546Sopenharmony_ci R64_C((const_base + 4) >> 1), /* SRC2 1128bf215546Sopenharmony_ci * (REGS64) 1129bf215546Sopenharmony_ci */ 1130bf215546Sopenharmony_ci R64_C((const_base + 6) >> 1) /* SRC3 1131bf215546Sopenharmony_ci * (REGS64C) 1132bf215546Sopenharmony_ci */ 1133bf215546Sopenharmony_ci )); 1134bf215546Sopenharmony_ci 1135bf215546Sopenharmony_ci /* Now the driver must have a dummy DDMAD marked as last. */ 1136bf215546Sopenharmony_ci if (last_DMA) { 1137bf215546Sopenharmony_ci uint32_t dummy_dma_const = pvr_find_constant(const_usage, 1138bf215546Sopenharmony_ci RESERVE_64BIT, 1139bf215546Sopenharmony_ci "uDummyDMAConst"); 1140bf215546Sopenharmony_ci uint32_t zero_const = 1141bf215546Sopenharmony_ci pvr_find_constant(const_usage, RESERVE_64BIT, "uZeroConst"); 1142bf215546Sopenharmony_ci 1143bf215546Sopenharmony_ci literal_entry = 1144bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1145bf215546Sopenharmony_ci sizeof(*literal_entry)); 1146bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 1147bf215546Sopenharmony_ci literal_entry->const_offset = zero_const; 1148bf215546Sopenharmony_ci literal_entry->literal_value = 0; 1149bf215546Sopenharmony_ci 1150bf215546Sopenharmony_ci literal_entry = 1151bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1152bf215546Sopenharmony_ci sizeof(*literal_entry)); 1153bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 1154bf215546Sopenharmony_ci literal_entry->const_offset = zero_const + 1; 1155bf215546Sopenharmony_ci literal_entry->literal_value = 0; 1156bf215546Sopenharmony_ci 1157bf215546Sopenharmony_ci literal_entry = 1158bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1159bf215546Sopenharmony_ci sizeof(*literal_entry)); 1160bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 1161bf215546Sopenharmony_ci literal_entry->const_offset = dummy_dma_const; 1162bf215546Sopenharmony_ci literal_entry->literal_value = 0; 1163bf215546Sopenharmony_ci 1164bf215546Sopenharmony_ci literal_entry->literal_value |= 1165bf215546Sopenharmony_ci 0 << PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_BSIZE_SHIFT; 1166bf215546Sopenharmony_ci literal_entry->literal_value |= 1167bf215546Sopenharmony_ci (PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_DEST_UNIFIED_STORE | 1168bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_CMODE_CACHED); 1169bf215546Sopenharmony_ci literal_entry->literal_value |= 1170bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_LAST_EN; 1171bf215546Sopenharmony_ci 1172bf215546Sopenharmony_ci literal_entry = 1173bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1174bf215546Sopenharmony_ci sizeof(*literal_entry)); 1175bf215546Sopenharmony_ci literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; 1176bf215546Sopenharmony_ci literal_entry->const_offset = dummy_dma_const + 1; 1177bf215546Sopenharmony_ci literal_entry->literal_value = 0; 1178bf215546Sopenharmony_ci 1179bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 1180bf215546Sopenharmony_ci instruction, 1181bf215546Sopenharmony_ci pvr_pds_inst_encode_ddmad( 1182bf215546Sopenharmony_ci 0, /* cc */ 1183bf215546Sopenharmony_ci 0, /* END */ 1184bf215546Sopenharmony_ci R32_C(zero_const), /* SRC0 (REGS32) 1185bf215546Sopenharmony_ci */ 1186bf215546Sopenharmony_ci R32_T(zero_temp), /* SRC1 (REGS32T) 1187bf215546Sopenharmony_ci */ 1188bf215546Sopenharmony_ci R64_C((dummy_dma_const) >> 1), /* SRC2 1189bf215546Sopenharmony_ci (REGS64) 1190bf215546Sopenharmony_ci */ 1191bf215546Sopenharmony_ci R64_C((dummy_dma_const) >> 1) /* SRC3 1192bf215546Sopenharmony_ci (REGS64C) 1193bf215546Sopenharmony_ci */ 1194bf215546Sopenharmony_ci )); 1195bf215546Sopenharmony_ci } 1196bf215546Sopenharmony_ci } 1197bf215546Sopenharmony_ci } else { 1198bf215546Sopenharmony_ci if (use_robust_vertex_fetch) { 1199bf215546Sopenharmony_ci struct pvr_const_map_entry_vertex_attribute_max_index 1200bf215546Sopenharmony_ci *max_index_entry; 1201bf215546Sopenharmony_ci 1202bf215546Sopenharmony_ci pvr_debug("RobustVertexFetch DDMAD"); 1203bf215546Sopenharmony_ci 1204bf215546Sopenharmony_ci const uint32_t max_index_const = 1205bf215546Sopenharmony_ci pvr_find_constant(const_usage, RESERVE_32BIT, "max_index_const"); 1206bf215546Sopenharmony_ci 1207bf215546Sopenharmony_ci max_index_entry = 1208bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1209bf215546Sopenharmony_ci sizeof(*max_index_entry)); 1210bf215546Sopenharmony_ci max_index_entry->const_offset = max_index_const; 1211bf215546Sopenharmony_ci max_index_entry->type = 1212bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTRIBUTE_MAX_INDEX; 1213bf215546Sopenharmony_ci max_index_entry->binding_index = vertex_dma->binding_index; 1214bf215546Sopenharmony_ci max_index_entry->offset = vertex_dma->offset; 1215bf215546Sopenharmony_ci max_index_entry->stride = vertex_dma->stride; 1216bf215546Sopenharmony_ci max_index_entry->size_in_dwords = vertex_dma->size_in_dwords; 1217bf215546Sopenharmony_ci max_index_entry->component_size_in_bytes = 1218bf215546Sopenharmony_ci vertex_dma->component_size_in_bytes; 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1221bf215546Sopenharmony_ci code, 1222bf215546Sopenharmony_ci instruction, 1223bf215546Sopenharmony_ci pvr_pds_inst_encode_add32(0, /* cc */ 1224bf215546Sopenharmony_ci 0, /* ALUM */ 1225bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_LOP_NONE, /* SNA */ 1226bf215546Sopenharmony_ci R32_C(max_index_const), /* SRC0 1227bf215546Sopenharmony_ci * (REGS32) 1228bf215546Sopenharmony_ci */ 1229bf215546Sopenharmony_ci R32_T(zero_temp), /* SRC1 (REGS32) */ 1230bf215546Sopenharmony_ci R32TP_T(max_index_temp) /* DST 1231bf215546Sopenharmony_ci * (REG32TP) 1232bf215546Sopenharmony_ci */ 1233bf215546Sopenharmony_ci )); 1234bf215546Sopenharmony_ci 1235bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 1236bf215546Sopenharmony_ci instruction, 1237bf215546Sopenharmony_ci pvr_pds_inst_encode_stflp32( 1238bf215546Sopenharmony_ci 1, /* IM */ 1239bf215546Sopenharmony_ci 0, /* cc */ 1240bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */ 1241bf215546Sopenharmony_ci index, /* SRC0 (REGS32T) */ 1242bf215546Sopenharmony_ci 0, /* SRC1 (REGS32) */ 1243bf215546Sopenharmony_ci 0, /* SRC2 (REG32TP) */ 1244bf215546Sopenharmony_ci R32TP_T(current_index_temp) /* DST 1245bf215546Sopenharmony_ci * (REG32TP) 1246bf215546Sopenharmony_ci */ 1247bf215546Sopenharmony_ci )); 1248bf215546Sopenharmony_ci 1249bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1250bf215546Sopenharmony_ci code, 1251bf215546Sopenharmony_ci instruction, 1252bf215546Sopenharmony_ci pvr_pds_inst_encode_cmp( 1253bf215546Sopenharmony_ci 0, /* cc enable */ 1254bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_COP_GT, /* Operation */ 1255bf215546Sopenharmony_ci R64TP_T(current_index_temp >> 1), /* SRC 1256bf215546Sopenharmony_ci * (REGS64TP) 1257bf215546Sopenharmony_ci */ 1258bf215546Sopenharmony_ci R64_T(max_index_temp >> 1) /* SRC1 (REGS64) */ 1259bf215546Sopenharmony_ci )); 1260bf215546Sopenharmony_ci 1261bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 1262bf215546Sopenharmony_ci instruction, 1263bf215546Sopenharmony_ci pvr_pds_inst_encode_stflp32( 1264bf215546Sopenharmony_ci 1, /* IM */ 1265bf215546Sopenharmony_ci 1, /* cc */ 1266bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_LOP_NONE, /* LOP */ 1267bf215546Sopenharmony_ci zero_temp, /* SRC0 (REGS32T) */ 1268bf215546Sopenharmony_ci 0, /* SRC1 (REGS32) */ 1269bf215546Sopenharmony_ci 0, /* SRC2 (REG32TP) */ 1270bf215546Sopenharmony_ci R32TP_T(current_index_temp) /* DST 1271bf215546Sopenharmony_ci * (REG32TP) 1272bf215546Sopenharmony_ci */ 1273bf215546Sopenharmony_ci )); 1274bf215546Sopenharmony_ci 1275bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 1276bf215546Sopenharmony_ci instruction, 1277bf215546Sopenharmony_ci pvr_pds_inst_encode_ddmad( 1278bf215546Sopenharmony_ci 0, /* cc */ 1279bf215546Sopenharmony_ci 0, /* END */ 1280bf215546Sopenharmony_ci R32_C(const_base + 3), /* SRC0 (REGS32) */ 1281bf215546Sopenharmony_ci current_index_temp, /* SRC1 (REGS32T) */ 1282bf215546Sopenharmony_ci R64_C((const_base + 4) >> 1), /* SRC2 1283bf215546Sopenharmony_ci * (REGS64) 1284bf215546Sopenharmony_ci */ 1285bf215546Sopenharmony_ci (const_base + 6) >> 1 /* SRC3 (REGS64C) */ 1286bf215546Sopenharmony_ci )); 1287bf215546Sopenharmony_ci } else { 1288bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, 1289bf215546Sopenharmony_ci instruction, 1290bf215546Sopenharmony_ci pvr_pds_inst_encode_ddmad( 1291bf215546Sopenharmony_ci /* cc */ 0, 1292bf215546Sopenharmony_ci /* end */ 0, 1293bf215546Sopenharmony_ci /* src0 */ R32_C(const_base + 3), 1294bf215546Sopenharmony_ci /* src2 */ (index), 1295bf215546Sopenharmony_ci /* src1 */ R64_C((const_base + 4) >> 1), 1296bf215546Sopenharmony_ci /* src3 */ (const_base + 6) >> 1)); 1297bf215546Sopenharmony_ci } 1298bf215546Sopenharmony_ci } 1299bf215546Sopenharmony_ci } 1300bf215546Sopenharmony_ci 1301bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_VERTEX_ID_REQUIRED) { 1302bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 1303bf215546Sopenharmony_ci 1304bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1305bf215546Sopenharmony_ci code, 1306bf215546Sopenharmony_ci instruction, 1307bf215546Sopenharmony_ci pvr_encode_direct_write( 1308bf215546Sopenharmony_ci &entry_write_state, 1309bf215546Sopenharmony_ci last_DMA, 1310bf215546Sopenharmony_ci false, 1311bf215546Sopenharmony_ci R64_C(write_vertex_control), 1312bf215546Sopenharmony_ci R64_T(0), 1313bf215546Sopenharmony_ci 0x1, 1314bf215546Sopenharmony_ci input_program->vertex_id_register, 1315bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1316bf215546Sopenharmony_ci dev_info)); 1317bf215546Sopenharmony_ci } 1318bf215546Sopenharmony_ci 1319bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_INSTANCE_ID_REQUIRED) { 1320bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 1321bf215546Sopenharmony_ci 1322bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1323bf215546Sopenharmony_ci code, 1324bf215546Sopenharmony_ci instruction, 1325bf215546Sopenharmony_ci pvr_encode_direct_write( 1326bf215546Sopenharmony_ci &entry_write_state, 1327bf215546Sopenharmony_ci last_DMA, 1328bf215546Sopenharmony_ci false, 1329bf215546Sopenharmony_ci R64_C(write_instance_control), 1330bf215546Sopenharmony_ci R64_T(0), 1331bf215546Sopenharmony_ci 0x2, 1332bf215546Sopenharmony_ci input_program->instance_id_register, 1333bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1334bf215546Sopenharmony_ci dev_info)); 1335bf215546Sopenharmony_ci } 1336bf215546Sopenharmony_ci 1337bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_INSTANCE_REQUIRED) { 1338bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 1339bf215546Sopenharmony_ci 1340bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) { 1341bf215546Sopenharmony_ci /* Base instance comes from ptemp 1. */ 1342bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1343bf215546Sopenharmony_ci code, 1344bf215546Sopenharmony_ci instruction, 1345bf215546Sopenharmony_ci pvr_encode_direct_write( 1346bf215546Sopenharmony_ci &entry_write_state, 1347bf215546Sopenharmony_ci last_DMA, 1348bf215546Sopenharmony_ci false, 1349bf215546Sopenharmony_ci R64_C(write_base_instance_control), 1350bf215546Sopenharmony_ci R64_P(PVR_INDIRECT_BASE_INSTANCE_PTEMP >> 1), 1351bf215546Sopenharmony_ci 0x2, 1352bf215546Sopenharmony_ci input_program->base_instance_register, 1353bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1354bf215546Sopenharmony_ci dev_info)); 1355bf215546Sopenharmony_ci } else { 1356bf215546Sopenharmony_ci uint32_t data_mask = (base_instance & 1) ? 0x2 : 0x1; 1357bf215546Sopenharmony_ci 1358bf215546Sopenharmony_ci /* Base instance comes from driver constant. */ 1359bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1360bf215546Sopenharmony_ci code, 1361bf215546Sopenharmony_ci instruction, 1362bf215546Sopenharmony_ci pvr_encode_direct_write( 1363bf215546Sopenharmony_ci &entry_write_state, 1364bf215546Sopenharmony_ci last_DMA, 1365bf215546Sopenharmony_ci false, 1366bf215546Sopenharmony_ci R64_C(write_base_instance_control), 1367bf215546Sopenharmony_ci R64_C(base_instance >> 1), 1368bf215546Sopenharmony_ci data_mask, 1369bf215546Sopenharmony_ci input_program->base_instance_register, 1370bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1371bf215546Sopenharmony_ci dev_info)); 1372bf215546Sopenharmony_ci } 1373bf215546Sopenharmony_ci } 1374bf215546Sopenharmony_ci 1375bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_BASE_VERTEX_REQUIRED) { 1376bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 1377bf215546Sopenharmony_ci 1378bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) { 1379bf215546Sopenharmony_ci /* Base vertex comes from ptemp 0 (initialized by PDS hardware). */ 1380bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1381bf215546Sopenharmony_ci code, 1382bf215546Sopenharmony_ci instruction, 1383bf215546Sopenharmony_ci pvr_encode_direct_write( 1384bf215546Sopenharmony_ci &entry_write_state, 1385bf215546Sopenharmony_ci last_DMA, 1386bf215546Sopenharmony_ci false, 1387bf215546Sopenharmony_ci R64_C(write_base_vertex_control), 1388bf215546Sopenharmony_ci R64_P(0), 1389bf215546Sopenharmony_ci 0x1, 1390bf215546Sopenharmony_ci input_program->base_vertex_register, 1391bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1392bf215546Sopenharmony_ci dev_info)); 1393bf215546Sopenharmony_ci } else { 1394bf215546Sopenharmony_ci uint32_t data_mask = (base_vertex & 1) ? 0x2 : 0x1; 1395bf215546Sopenharmony_ci 1396bf215546Sopenharmony_ci /* Base vertex comes from driver constant (literal 0). */ 1397bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1398bf215546Sopenharmony_ci code, 1399bf215546Sopenharmony_ci instruction, 1400bf215546Sopenharmony_ci pvr_encode_direct_write( 1401bf215546Sopenharmony_ci &entry_write_state, 1402bf215546Sopenharmony_ci last_DMA, 1403bf215546Sopenharmony_ci false, 1404bf215546Sopenharmony_ci R64_C(write_base_vertex_control), 1405bf215546Sopenharmony_ci R64_C(base_vertex >> 1), 1406bf215546Sopenharmony_ci data_mask, 1407bf215546Sopenharmony_ci input_program->base_vertex_register, 1408bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1409bf215546Sopenharmony_ci dev_info)); 1410bf215546Sopenharmony_ci } 1411bf215546Sopenharmony_ci } 1412bf215546Sopenharmony_ci 1413bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDEX_REQUIRED) { 1414bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 1415bf215546Sopenharmony_ci 1416bf215546Sopenharmony_ci if (input_program->flags & PVR_PDS_VERTEX_FLAGS_DRAW_INDIRECT_VARIANT) { 1417bf215546Sopenharmony_ci /* Draw index comes from ptemp 3. */ 1418bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1419bf215546Sopenharmony_ci code, 1420bf215546Sopenharmony_ci instruction, 1421bf215546Sopenharmony_ci pvr_encode_direct_write( 1422bf215546Sopenharmony_ci &entry_write_state, 1423bf215546Sopenharmony_ci last_DMA, 1424bf215546Sopenharmony_ci false, 1425bf215546Sopenharmony_ci R64_C(pvr_write_draw_index_control), 1426bf215546Sopenharmony_ci R64_P(1), 1427bf215546Sopenharmony_ci 0x2, 1428bf215546Sopenharmony_ci input_program->draw_index_register, 1429bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1430bf215546Sopenharmony_ci dev_info)); 1431bf215546Sopenharmony_ci } else { 1432bf215546Sopenharmony_ci uint32_t data_mask = (draw_index & 1) ? 0x2 : 0x1; 1433bf215546Sopenharmony_ci 1434bf215546Sopenharmony_ci /* Draw index comes from constant (literal 0). */ 1435bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1436bf215546Sopenharmony_ci code, 1437bf215546Sopenharmony_ci instruction, 1438bf215546Sopenharmony_ci pvr_encode_direct_write( 1439bf215546Sopenharmony_ci &entry_write_state, 1440bf215546Sopenharmony_ci last_DMA, 1441bf215546Sopenharmony_ci false, 1442bf215546Sopenharmony_ci R64_C(pvr_write_draw_index_control), 1443bf215546Sopenharmony_ci R64_C(draw_index >> 1), 1444bf215546Sopenharmony_ci data_mask, 1445bf215546Sopenharmony_ci input_program->draw_index_register, 1446bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_DOUT_FIELDS_DOUTW_SRC1_DEST_UNIFIED_STORE, 1447bf215546Sopenharmony_ci dev_info)); 1448bf215546Sopenharmony_ci } 1449bf215546Sopenharmony_ci } 1450bf215546Sopenharmony_ci 1451bf215546Sopenharmony_ci doutu_address_entry = 1452bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1453bf215546Sopenharmony_ci sizeof(*doutu_address_entry)); 1454bf215546Sopenharmony_ci doutu_address_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_DOUTU_ADDRESS; 1455bf215546Sopenharmony_ci doutu_address_entry->const_offset = 0; 1456bf215546Sopenharmony_ci doutu_address_entry->doutu_control = input_program->usc_task_control.src0; 1457bf215546Sopenharmony_ci 1458bf215546Sopenharmony_ci if (use_robust_vertex_fetch) { 1459bf215546Sopenharmony_ci /* Restore IF0 */ 1460bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE( 1461bf215546Sopenharmony_ci code, 1462bf215546Sopenharmony_ci instruction, 1463bf215546Sopenharmony_ci pvr_pds_inst_encode_bra(PVR_ROGUE_PDSINST_PREDICATE_KEEP, /* SRCCC */ 1464bf215546Sopenharmony_ci 0, /* Neg */ 1465bf215546Sopenharmony_ci PVR_ROGUE_PDSINST_PREDICATE_IF0, /* SETCC */ 1466bf215546Sopenharmony_ci 1 /* Addr */ 1467bf215546Sopenharmony_ci )); 1468bf215546Sopenharmony_ci } 1469bf215546Sopenharmony_ci 1470bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, instruction, pvr_pds_encode_doutu(1, 1, 0)); 1471bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code, instruction, pvr_pds_inst_encode_halt(0)); 1472bf215546Sopenharmony_ci 1473bf215546Sopenharmony_ci assert(running_dma_count == total_dma_count); 1474bf215546Sopenharmony_ci 1475bf215546Sopenharmony_ci for (uint32_t i = 0; i < ARRAY_SIZE(const_usage); i++) { 1476bf215546Sopenharmony_ci if (const_usage[i] == 0) 1477bf215546Sopenharmony_ci break; 1478bf215546Sopenharmony_ci 1479bf215546Sopenharmony_ci info->data_size_in_dwords = 1480bf215546Sopenharmony_ci 8 * i + (32 - __builtin_clz((uint32_t)const_usage[i])); 1481bf215546Sopenharmony_ci } 1482bf215546Sopenharmony_ci 1483bf215546Sopenharmony_ci info->temps_required = temp_usage.temps_needed; 1484bf215546Sopenharmony_ci info->entry_count = entry_write_state.entry_count; 1485bf215546Sopenharmony_ci info->entries_written_size_in_bytes = 1486bf215546Sopenharmony_ci entry_write_state.entries_size_in_bytes; 1487bf215546Sopenharmony_ci info->code_size_in_dwords = instruction; 1488bf215546Sopenharmony_ci 1489bf215546Sopenharmony_ci pvr_debug("=================================================\n"); 1490bf215546Sopenharmony_ci} 1491bf215546Sopenharmony_ci 1492bf215546Sopenharmony_civoid pvr_pds_generate_descriptor_upload_program( 1493bf215546Sopenharmony_ci struct pvr_descriptor_program_input *input_program, 1494bf215546Sopenharmony_ci uint32_t *code_section, 1495bf215546Sopenharmony_ci struct pvr_pds_info *info) 1496bf215546Sopenharmony_ci{ 1497bf215546Sopenharmony_ci unsigned int num_consts64; 1498bf215546Sopenharmony_ci unsigned int num_consts32; 1499bf215546Sopenharmony_ci unsigned int next_const64; 1500bf215546Sopenharmony_ci unsigned int next_const32; 1501bf215546Sopenharmony_ci unsigned int instruction = 0; 1502bf215546Sopenharmony_ci uint32_t compile_time_buffer_index = 0; 1503bf215546Sopenharmony_ci 1504bf215546Sopenharmony_ci unsigned int total_dma_count = 0; 1505bf215546Sopenharmony_ci unsigned int running_dma_count = 0; 1506bf215546Sopenharmony_ci 1507bf215546Sopenharmony_ci struct pvr_pds_const_map_entry_write_state entry_write_state; 1508bf215546Sopenharmony_ci 1509bf215546Sopenharmony_ci /* Calculate the total register usage so we can stick 32-bit consts 1510bf215546Sopenharmony_ci * after 64. Each DOUTD/DDMAD requires 1 32-bit constant and 1 64-bit 1511bf215546Sopenharmony_ci * constant. 1512bf215546Sopenharmony_ci */ 1513bf215546Sopenharmony_ci num_consts32 = input_program->descriptor_set_count; 1514bf215546Sopenharmony_ci num_consts64 = input_program->descriptor_set_count; 1515bf215546Sopenharmony_ci total_dma_count = input_program->descriptor_set_count; 1516bf215546Sopenharmony_ci 1517bf215546Sopenharmony_ci pvr_init_pds_const_map_entry_write_state(info, &entry_write_state); 1518bf215546Sopenharmony_ci 1519bf215546Sopenharmony_ci for (unsigned int index = 0; index < input_program->buffer_count; index++) { 1520bf215546Sopenharmony_ci struct pvr_pds_buffer *buffer = &input_program->buffers[index]; 1521bf215546Sopenharmony_ci 1522bf215546Sopenharmony_ci /* This switch statement looks pointless but we want to optimize DMAs 1523bf215546Sopenharmony_ci * that can be done as a DOUTW. 1524bf215546Sopenharmony_ci */ 1525bf215546Sopenharmony_ci switch (buffer->type) { 1526bf215546Sopenharmony_ci default: { 1527bf215546Sopenharmony_ci /* 1 DOUTD per compile time buffer: */ 1528bf215546Sopenharmony_ci num_consts32++; 1529bf215546Sopenharmony_ci num_consts64++; 1530bf215546Sopenharmony_ci total_dma_count++; 1531bf215546Sopenharmony_ci break; 1532bf215546Sopenharmony_ci } 1533bf215546Sopenharmony_ci } 1534bf215546Sopenharmony_ci } 1535bf215546Sopenharmony_ci 1536bf215546Sopenharmony_ci /* DOUTU for the secondary update program requires a 64-bit constant. */ 1537bf215546Sopenharmony_ci if (input_program->secondary_program_present) 1538bf215546Sopenharmony_ci num_consts64++; 1539bf215546Sopenharmony_ci 1540bf215546Sopenharmony_ci info->data_size_in_dwords = (num_consts64 * 2) + (num_consts32); 1541bf215546Sopenharmony_ci 1542bf215546Sopenharmony_ci /* Start counting constants. */ 1543bf215546Sopenharmony_ci next_const64 = 0; 1544bf215546Sopenharmony_ci next_const32 = num_consts64 * 2; 1545bf215546Sopenharmony_ci 1546bf215546Sopenharmony_ci /* For each descriptor set perform a DOUTD. */ 1547bf215546Sopenharmony_ci for (unsigned int descriptor_index = 0; 1548bf215546Sopenharmony_ci descriptor_index < input_program->descriptor_set_count; 1549bf215546Sopenharmony_ci descriptor_index++) { 1550bf215546Sopenharmony_ci struct pvr_const_map_entry_descriptor_set *descriptor_set_entry; 1551bf215546Sopenharmony_ci struct pvr_pds_descriptor_set *descriptor_set = 1552bf215546Sopenharmony_ci &input_program->descriptor_sets[descriptor_index]; 1553bf215546Sopenharmony_ci 1554bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 1555bf215546Sopenharmony_ci bool halt = last_DMA && !input_program->secondary_program_present; 1556bf215546Sopenharmony_ci 1557bf215546Sopenharmony_ci descriptor_set_entry = 1558bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1559bf215546Sopenharmony_ci sizeof(*descriptor_set_entry)); 1560bf215546Sopenharmony_ci descriptor_set_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_DESCRIPTOR_SET; 1561bf215546Sopenharmony_ci descriptor_set_entry->const_offset = next_const64 * 2; 1562bf215546Sopenharmony_ci descriptor_set_entry->descriptor_set = descriptor_set->descriptor_set; 1563bf215546Sopenharmony_ci descriptor_set_entry->primary = descriptor_set->primary; 1564bf215546Sopenharmony_ci descriptor_set_entry->offset_in_dwords = descriptor_set->offset_in_dwords; 1565bf215546Sopenharmony_ci 1566bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code_section, 1567bf215546Sopenharmony_ci instruction, 1568bf215546Sopenharmony_ci pvr_encode_burst_cs(&entry_write_state, 1569bf215546Sopenharmony_ci last_DMA, 1570bf215546Sopenharmony_ci halt, 1571bf215546Sopenharmony_ci next_const32, 1572bf215546Sopenharmony_ci next_const64, 1573bf215546Sopenharmony_ci descriptor_set->size_in_dwords, 1574bf215546Sopenharmony_ci descriptor_set->destination)); 1575bf215546Sopenharmony_ci 1576bf215546Sopenharmony_ci next_const64++; 1577bf215546Sopenharmony_ci next_const32++; 1578bf215546Sopenharmony_ci } 1579bf215546Sopenharmony_ci 1580bf215546Sopenharmony_ci for (unsigned int index = 0; index < input_program->buffer_count; index++) { 1581bf215546Sopenharmony_ci struct pvr_pds_buffer *buffer = &input_program->buffers[index]; 1582bf215546Sopenharmony_ci 1583bf215546Sopenharmony_ci bool last_DMA = (++running_dma_count == total_dma_count); 1584bf215546Sopenharmony_ci bool halt = last_DMA && !input_program->secondary_program_present; 1585bf215546Sopenharmony_ci 1586bf215546Sopenharmony_ci switch (buffer->type) { 1587bf215546Sopenharmony_ci case PVR_BUFFER_TYPE_PUSH_CONSTS: { 1588bf215546Sopenharmony_ci struct pvr_const_map_entry_special_buffer *special_buffer_entry; 1589bf215546Sopenharmony_ci 1590bf215546Sopenharmony_ci special_buffer_entry = 1591bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1592bf215546Sopenharmony_ci sizeof(*special_buffer_entry)); 1593bf215546Sopenharmony_ci special_buffer_entry->type = 1594bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER; 1595bf215546Sopenharmony_ci special_buffer_entry->buffer_type = PVR_BUFFER_TYPE_PUSH_CONSTS; 1596bf215546Sopenharmony_ci special_buffer_entry->buffer_index = buffer->source_offset; 1597bf215546Sopenharmony_ci break; 1598bf215546Sopenharmony_ci } 1599bf215546Sopenharmony_ci case PVR_BUFFER_TYPE_DYNAMIC: { 1600bf215546Sopenharmony_ci struct pvr_const_map_entry_special_buffer *special_buffer_entry; 1601bf215546Sopenharmony_ci 1602bf215546Sopenharmony_ci special_buffer_entry = 1603bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1604bf215546Sopenharmony_ci sizeof(*special_buffer_entry)); 1605bf215546Sopenharmony_ci special_buffer_entry->type = 1606bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER; 1607bf215546Sopenharmony_ci special_buffer_entry->buffer_type = PVR_BUFFER_TYPE_DYNAMIC; 1608bf215546Sopenharmony_ci special_buffer_entry->buffer_index = buffer->source_offset; 1609bf215546Sopenharmony_ci break; 1610bf215546Sopenharmony_ci } 1611bf215546Sopenharmony_ci case PVR_BUFFER_TYPES_COMPILE_TIME: { 1612bf215546Sopenharmony_ci struct pvr_const_map_entry_special_buffer *special_buffer_entry; 1613bf215546Sopenharmony_ci 1614bf215546Sopenharmony_ci special_buffer_entry = 1615bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1616bf215546Sopenharmony_ci sizeof(*special_buffer_entry)); 1617bf215546Sopenharmony_ci special_buffer_entry->type = 1618bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER; 1619bf215546Sopenharmony_ci special_buffer_entry->buffer_type = PVR_BUFFER_TYPES_COMPILE_TIME; 1620bf215546Sopenharmony_ci special_buffer_entry->buffer_index = compile_time_buffer_index++; 1621bf215546Sopenharmony_ci break; 1622bf215546Sopenharmony_ci } 1623bf215546Sopenharmony_ci case PVR_BUFFER_TYPES_BUFFER_LENGTHS: { 1624bf215546Sopenharmony_ci struct pvr_const_map_entry_special_buffer *special_buffer_entry; 1625bf215546Sopenharmony_ci 1626bf215546Sopenharmony_ci special_buffer_entry = 1627bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1628bf215546Sopenharmony_ci sizeof(*special_buffer_entry)); 1629bf215546Sopenharmony_ci special_buffer_entry->type = 1630bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER; 1631bf215546Sopenharmony_ci special_buffer_entry->buffer_type = PVR_BUFFER_TYPES_BUFFER_LENGTHS; 1632bf215546Sopenharmony_ci break; 1633bf215546Sopenharmony_ci } 1634bf215546Sopenharmony_ci case PVR_BUFFER_TYPE_BLEND_CONSTS: { 1635bf215546Sopenharmony_ci struct pvr_const_map_entry_special_buffer *special_buffer_entry; 1636bf215546Sopenharmony_ci 1637bf215546Sopenharmony_ci special_buffer_entry = 1638bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1639bf215546Sopenharmony_ci sizeof(*special_buffer_entry)); 1640bf215546Sopenharmony_ci special_buffer_entry->type = 1641bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_SPECIAL_BUFFER; 1642bf215546Sopenharmony_ci special_buffer_entry->buffer_type = PVR_BUFFER_TYPE_BLEND_CONSTS; 1643bf215546Sopenharmony_ci special_buffer_entry->buffer_index = 1644bf215546Sopenharmony_ci input_program->blend_constants_used_mask; 1645bf215546Sopenharmony_ci break; 1646bf215546Sopenharmony_ci } 1647bf215546Sopenharmony_ci case PVR_BUFFER_TYPE_UBO: { 1648bf215546Sopenharmony_ci struct pvr_const_map_entry_constant_buffer *constant_buffer_entry; 1649bf215546Sopenharmony_ci 1650bf215546Sopenharmony_ci constant_buffer_entry = pvr_prepare_next_pds_const_map_entry( 1651bf215546Sopenharmony_ci &entry_write_state, 1652bf215546Sopenharmony_ci sizeof(*constant_buffer_entry)); 1653bf215546Sopenharmony_ci constant_buffer_entry->type = 1654bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_CONSTANT_BUFFER; 1655bf215546Sopenharmony_ci constant_buffer_entry->buffer_id = buffer->buffer_id; 1656bf215546Sopenharmony_ci constant_buffer_entry->desc_set = buffer->desc_set; 1657bf215546Sopenharmony_ci constant_buffer_entry->binding = buffer->binding; 1658bf215546Sopenharmony_ci constant_buffer_entry->offset = buffer->source_offset; 1659bf215546Sopenharmony_ci constant_buffer_entry->size_in_dwords = buffer->size_in_dwords; 1660bf215546Sopenharmony_ci break; 1661bf215546Sopenharmony_ci } 1662bf215546Sopenharmony_ci case PVR_BUFFER_TYPES_UBO_ZEROING: { 1663bf215546Sopenharmony_ci struct pvr_const_map_entry_constant_buffer_zeroing 1664bf215546Sopenharmony_ci *constant_buffer_entry; 1665bf215546Sopenharmony_ci 1666bf215546Sopenharmony_ci constant_buffer_entry = pvr_prepare_next_pds_const_map_entry( 1667bf215546Sopenharmony_ci &entry_write_state, 1668bf215546Sopenharmony_ci sizeof(*constant_buffer_entry)); 1669bf215546Sopenharmony_ci constant_buffer_entry->type = 1670bf215546Sopenharmony_ci PVR_PDS_CONST_MAP_ENTRY_TYPE_CONSTANT_BUFFER_ZEROING; 1671bf215546Sopenharmony_ci constant_buffer_entry->buffer_id = buffer->buffer_id; 1672bf215546Sopenharmony_ci constant_buffer_entry->offset = buffer->source_offset; 1673bf215546Sopenharmony_ci constant_buffer_entry->size_in_dwords = buffer->size_in_dwords; 1674bf215546Sopenharmony_ci break; 1675bf215546Sopenharmony_ci } 1676bf215546Sopenharmony_ci } 1677bf215546Sopenharmony_ci 1678bf215546Sopenharmony_ci entry_write_state.entry->const_offset = next_const64 * 2; 1679bf215546Sopenharmony_ci 1680bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code_section, 1681bf215546Sopenharmony_ci instruction, 1682bf215546Sopenharmony_ci pvr_encode_burst_cs(&entry_write_state, 1683bf215546Sopenharmony_ci last_DMA, 1684bf215546Sopenharmony_ci halt, 1685bf215546Sopenharmony_ci next_const32, 1686bf215546Sopenharmony_ci next_const64, 1687bf215546Sopenharmony_ci buffer->size_in_dwords, 1688bf215546Sopenharmony_ci buffer->destination)); 1689bf215546Sopenharmony_ci 1690bf215546Sopenharmony_ci next_const64++; 1691bf215546Sopenharmony_ci next_const32++; 1692bf215546Sopenharmony_ci } 1693bf215546Sopenharmony_ci 1694bf215546Sopenharmony_ci if (total_dma_count != running_dma_count) 1695bf215546Sopenharmony_ci fprintf(stderr, "Mismatch in DMA count\n"); 1696bf215546Sopenharmony_ci 1697bf215546Sopenharmony_ci if (input_program->secondary_program_present) { 1698bf215546Sopenharmony_ci struct pvr_const_map_entry_doutu_address *doutu_address; 1699bf215546Sopenharmony_ci 1700bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code_section, 1701bf215546Sopenharmony_ci instruction, 1702bf215546Sopenharmony_ci pvr_pds_encode_doutu(false, true, next_const64)); 1703bf215546Sopenharmony_ci 1704bf215546Sopenharmony_ci doutu_address = 1705bf215546Sopenharmony_ci pvr_prepare_next_pds_const_map_entry(&entry_write_state, 1706bf215546Sopenharmony_ci sizeof(*doutu_address)); 1707bf215546Sopenharmony_ci doutu_address->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_DOUTU_ADDRESS; 1708bf215546Sopenharmony_ci doutu_address->const_offset = next_const64 * 2; 1709bf215546Sopenharmony_ci doutu_address->doutu_control = input_program->secondary_task_control.src0; 1710bf215546Sopenharmony_ci 1711bf215546Sopenharmony_ci next_const64++; 1712bf215546Sopenharmony_ci } 1713bf215546Sopenharmony_ci 1714bf215546Sopenharmony_ci if (instruction == 0 && input_program->must_not_be_empty) { 1715bf215546Sopenharmony_ci PVR_PDS_MODE_TOGGLE(code_section, 1716bf215546Sopenharmony_ci instruction, 1717bf215546Sopenharmony_ci pvr_pds_inst_encode_halt( 1718bf215546Sopenharmony_ci /* cc */ false)); 1719bf215546Sopenharmony_ci } 1720bf215546Sopenharmony_ci 1721bf215546Sopenharmony_ci info->entry_count = entry_write_state.entry_count; 1722bf215546Sopenharmony_ci info->entries_written_size_in_bytes = 1723bf215546Sopenharmony_ci entry_write_state.entries_size_in_bytes; 1724bf215546Sopenharmony_ci info->code_size_in_dwords = instruction; 1725bf215546Sopenharmony_ci} 1726