1 /*
2 * Copyright 2022 Alyssa Rosenzweig
3 * SPDX-License-Identifier: MIT
4 */
5
6 #pragma once
7
8 #include "asahi/genxml/agx_pack.h"
9 #include "agx_compile.h"
10 #include "libagx_dgc.h"
11 #include "shader_enums.h"
12
13 static inline unsigned
agx_usc_size(unsigned num_reg_bindings)14 agx_usc_size(unsigned num_reg_bindings)
15 {
16 STATIC_ASSERT(AGX_USC_UNIFORM_HIGH_LENGTH == AGX_USC_UNIFORM_LENGTH);
17 STATIC_ASSERT(AGX_USC_TEXTURE_LENGTH == AGX_USC_UNIFORM_LENGTH);
18 STATIC_ASSERT(AGX_USC_SAMPLER_LENGTH == AGX_USC_UNIFORM_LENGTH);
19
20 size_t size = AGX_USC_UNIFORM_LENGTH * num_reg_bindings;
21
22 size += AGX_USC_SHARED_LENGTH;
23 size += AGX_USC_SHADER_LENGTH;
24 size += AGX_USC_REGISTERS_LENGTH;
25 size += MAX2(AGX_USC_NO_PRESHADER_LENGTH, AGX_USC_PRESHADER_LENGTH);
26 size += AGX_USC_FRAGMENT_PROPERTIES_LENGTH;
27
28 return size;
29 }
30
31 static void
agx_usc_shared_none(struct agx_usc_builder * b)32 agx_usc_shared_none(struct agx_usc_builder *b)
33 {
34 agx_usc_pack(b, SHARED, cfg) {
35 cfg.layout = AGX_SHARED_LAYOUT_VERTEX_COMPUTE;
36 cfg.bytes_per_threadgroup = 65536;
37 }
38 }
39
40 static inline void
agx_usc_shared(struct agx_usc_builder * b,uint16_t local_size,uint16_t imageblock_stride,unsigned variable_shared_mem)41 agx_usc_shared(struct agx_usc_builder *b, uint16_t local_size,
42 uint16_t imageblock_stride, unsigned variable_shared_mem)
43 {
44 if (imageblock_stride) {
45 assert(local_size == 0 && "we don't handle this interaction");
46 assert(variable_shared_mem == 0 && "we don't handle this interaction");
47
48 agx_usc_pack(b, SHARED, cfg) {
49 cfg.layout = AGX_SHARED_LAYOUT_32X32;
50 cfg.uses_shared_memory = true;
51 cfg.sample_count = 1;
52 cfg.sample_stride_in_8_bytes = DIV_ROUND_UP(imageblock_stride, 8);
53 cfg.bytes_per_threadgroup = cfg.sample_stride_in_8_bytes * 8 * 32 * 32;
54 }
55 } else if (local_size || variable_shared_mem) {
56 unsigned size = local_size + variable_shared_mem;
57
58 agx_usc_pack(b, SHARED, cfg) {
59 cfg.layout = AGX_SHARED_LAYOUT_VERTEX_COMPUTE;
60 cfg.bytes_per_threadgroup = size > 0 ? size : 65536;
61 cfg.uses_shared_memory = size > 0;
62 }
63 } else {
64 agx_usc_shared_none(b);
65 }
66 }
67
68 static inline void
agx_usc_immediates(struct agx_usc_builder * b,const struct agx_rodata * ro,uint64_t base_addr)69 agx_usc_immediates(struct agx_usc_builder *b, const struct agx_rodata *ro,
70 uint64_t base_addr)
71 {
72 for (unsigned range = 0; range < DIV_ROUND_UP(ro->size_16, 64); ++range) {
73 unsigned offset = 64 * range;
74 assert(offset < ro->size_16);
75
76 agx_usc_uniform(b, ro->base_uniform + offset,
77 MIN2(64, ro->size_16 - offset),
78 base_addr + ro->offset + (offset * 2));
79 }
80 }
81
82 static void
agx_usc_shared_non_fragment(struct agx_usc_builder * b,const struct agx_shader_info * info,unsigned variable_shared_mem)83 agx_usc_shared_non_fragment(struct agx_usc_builder *b,
84 const struct agx_shader_info *info,
85 unsigned variable_shared_mem)
86 {
87 if (info->stage != PIPE_SHADER_FRAGMENT) {
88 agx_usc_shared(b, info->local_size, info->imageblock_stride,
89 variable_shared_mem);
90 }
91 }
92