A Modern GPGPU API & wip linux RDNA2+ Driver
rdna driver linux gpu
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

amdgpu: wip compute shader dispatch

+97 -9
+86
drivers/amdgpu/cmds.cpp
··· 1 + #include "gpuinfo.h" 1 2 #include "kestrel/kestrel.h" 2 3 #include "impl.h" 3 4 5 + #include "amdgfxregs.h" 6 + #include "sid.h" 7 + #include <amdgpu_drm.h> 8 + 9 + #include "pm4_encoder.h" 4 10 #include "sdma_encoder.h" 11 + #include <cstdint> 5 12 6 13 void memset_transfer(CommandListImpl *impl, kes_gpuptr_t addr, std::size_t size, uint32_t value) { 7 14 assert(impl->queue->type == KesQueueTypeTransfer, "memset_transfer: requires queue of Transfer type"); ··· 143 150 not_implemented("write_timestamp: not implemented for queue type: {}", cl->queue->type); 144 151 } 145 152 } 153 + 154 + struct Shader {}; 155 + 156 + struct DispatchInfo { 157 + uint32_t x; 158 + uint32_t y; 159 + uint32_t z; 160 + uint64_t indirect_va; 161 + }; 162 + 163 + void amdgpu_emit_dispatch_packets(GpuInfo &ginfo, Pm4Encoder &enc, Shader &shader, DispatchInfo &dinfo) { 164 + 165 + // @todo: get this from device settings 166 + uint32_t dispatch_initiator = S_00B800_COMPUTE_SHADER_EN(1) | S_00B800_TUNNEL_ENABLE(1); 167 + 168 + // @todo: support predicating 169 + auto predicating = false; 170 + 171 + // @todo: support 172 + auto ordered = false; 173 + if (ordered) { 174 + dispatch_initiator &= ~S_00B800_ORDER_MODE(1); 175 + } 176 + 177 + // @todo: get from shader info 178 + auto wave_size = 32; 179 + if (wave_size == 32) { 180 + dispatch_initiator |= S_00B800_CS_W32_EN(1); 181 + } 182 + 183 + if (dinfo.indirect_va) { 184 + // mesa align32 workaround not needed; only for GFX7 185 + enc.emit(PKT3(PKT3_DISPATCH_INDIRECT, 2, 0) | PKT3_SHADER_TYPE_S(1)); 186 + enc.emit(dinfo.indirect_va); 187 + enc.emit(dinfo.indirect_va >> 32); 188 + enc.emit(dispatch_initiator); 189 + } else { 190 + // @todo: load block-size into shader regs. 191 + // @todo: unaligned? 192 + enc.emit(PKT3(PKT3_DISPATCH_DIRECT, 3, predicating) | PKT3_SHADER_TYPE_S(1)); 193 + enc.emit(dinfo.x); 194 + enc.emit(dinfo.y); 195 + enc.emit(dinfo.z); 196 + enc.emit(dispatch_initiator); 197 + } 198 + } 199 + 200 + void amdgpu_cmd_dispatch(KesCommandList pcl, uint32_t x, uint32_t y, uint32_t z) { 201 + auto *cl = reinterpret_cast<CommandListImpl *>(pcl); 202 + assert(cl, "dispatch: command list handle invalid: {}", (void *)pcl); 203 + 204 + auto hw_ip_type = hw_ip_type_from_queue_type(cl->queue->type); 205 + Pm4Encoder enc(cl->queue->dev->info, hw_ip_type, cl->cs); 206 + 207 + Shader tmp{}; 208 + DispatchInfo dinfo{ 209 + .x = x, 210 + .y = y, 211 + .z = z, 212 + .indirect_va = 0 213 + }; 214 + 215 + amdgpu_emit_dispatch_packets(cl->queue->dev->info, enc, tmp, dinfo); 216 + } 217 + 218 + void amdgpu_cmd_dispatch_indirect(KesCommandList pcl, uint64_t indirect_addr) { 219 + auto *cl = reinterpret_cast<CommandListImpl *>(pcl); 220 + assert(cl, "dispatch: command list handle invalid: {}", (void *)pcl); 221 + 222 + auto hw_ip_type = hw_ip_type_from_queue_type(cl->queue->type); 223 + Pm4Encoder enc(cl->queue->dev->info, hw_ip_type, cl->cs); 224 + 225 + Shader tmp{}; 226 + DispatchInfo dinfo{ 227 + .indirect_va = indirect_addr 228 + }; 229 + 230 + amdgpu_emit_dispatch_packets(cl->queue->dev->info, enc, tmp, dinfo); 231 + }
+4
drivers/amdgpu/impl.h
··· 52 52 53 53 void amdgpu_cmd_signal_after(KesCommandList, KesStage before, kes_gpuptr_t addr, uint64_t value, KesSignal); 54 54 void amdgpu_cmd_wait_before(KesCommandList, KesStage after, kes_gpuptr_t addr, uint64_t value, KesOp, KesHazardFlags, uint64_t mask); 55 + void amdgpu_cmd_dispatch(KesCommandList pcl, uint32_t x, uint32_t y, uint32_t z); 56 + void amdgpu_cmd_dispatch_indirect(KesCommandList pcl, uint64_t indirect_addr); 55 57 } 58 + 59 + uint32_t hw_ip_type_from_queue_type(KesQueueType qt);
+2
drivers/amdgpu/interface.cpp
··· 19 19 fns->fn_cmd_write_timestamp = amdgpu_cmd_write_timestamp; 20 20 fns->fn_cmd_signal_after = amdgpu_cmd_signal_after; 21 21 fns->fn_cmd_wait_before = amdgpu_cmd_wait_before; 22 + fns->fn_cmd_dispatch = amdgpu_cmd_dispatch; 23 + fns->fn_cmd_dispatch_indirect = amdgpu_cmd_dispatch_indirect; 22 24 }
+2 -6
drivers/amdgpu/pm4_encoder.cpp
··· 7 7 #include "sid.h" 8 8 #include <amdgpu_drm.h> 9 9 10 - Pm4Encoder::Pm4Encoder(GpuInfo &info, uint8_t ip_type) : info(info), ip_type(ip_type) { 10 + Pm4Encoder::Pm4Encoder(GpuInfo &info, uint8_t ip_type, CommandStream &cs) : info(info), ip_type(ip_type), cs(cs) { 11 11 12 12 } 13 13 14 14 void Pm4Encoder::emit(uint32_t value) { 15 - buf.push_back(value); 16 - } 17 - 18 - void Pm4Encoder::emit(std::span<uint32_t> values) { 19 - buf.insert(buf.end(), values.begin(), values.end()); 15 + cs.emit(value); 20 16 } 21 17 22 18 void Pm4Encoder::set_reg_seq(uint32_t reg, uint32_t num, uint32_t idx, uint32_t bank_offset, uint32_t bank_end, uint32_t packet, uint32_t reset_filter_cam) {
+3 -3
drivers/amdgpu/pm4_encoder.h
··· 3 3 #include <span> 4 4 #include <vector> 5 5 6 + #include "cmdstream.h" 6 7 #include "gpuinfo.h" 7 8 8 9 class Pm4Encoder { 9 10 public: 10 - Pm4Encoder(GpuInfo &info, uint8_t ip_type); 11 + Pm4Encoder(GpuInfo &info, uint8_t ip_type, CommandStream &cs); 11 12 12 13 void emit(uint32_t value); 13 - void emit(std::span<uint32_t> values); 14 14 15 15 void emit_32bit_pointer(uint32_t sh_offset, uint64_t va); 16 16 void emit_64bit_pointer(uint32_t sh_offset, uint64_t va); ··· 49 49 50 50 GpuInfo &info; 51 51 uint8_t ip_type; 52 + CommandStream &cs; 52 53 53 - std::vector<uint32_t> buf; 54 54 bool context_roll; 55 55 };