| ... | ... | @@ -368,6 +368,40 @@ fn processTypeInstruction(self: *Assembler) !AsmValue { |
| 368 | 368 | }); |
| 369 | 369 | break :blk result_id; |
| 370 | 370 | }, |
| 371 | .OpTypeStruct => blk: { |
| 372 | const ids = try self.gpa.alloc(IdRef, operands[1..].len); |
| 373 | defer self.gpa.free(ids); |
| 374 | for (operands[1..], ids) |op, *id| id.* = try self.resolveRefId(op.ref_id); |
| 375 | const result_id = self.spv.allocId(); |
| 376 | try self.spv.structType(result_id, ids, null); |
| 377 | break :blk result_id; |
| 378 | }, |
| 379 | .OpTypeImage => blk: { |
| 380 | const sampled_type = try self.resolveRefId(operands[1].ref_id); |
| 381 | const result_id = self.spv.allocId(); |
| 382 | try section.emit(self.gpa, .OpTypeImage, .{ |
| 383 | .id_result = result_id, |
| 384 | .sampled_type = sampled_type, |
| 385 | .dim = @enumFromInt(operands[2].value), |
| 386 | .depth = operands[3].literal32, |
| 387 | .arrayed = operands[4].literal32, |
| 388 | .ms = operands[5].literal32, |
| 389 | .sampled = operands[6].literal32, |
| 390 | .image_format = @enumFromInt(operands[7].value), |
| 391 | }); |
| 392 | break :blk result_id; |
| 393 | }, |
| 394 | .OpTypeSampler => blk: { |
| 395 | const result_id = self.spv.allocId(); |
| 396 | try section.emit(self.gpa, .OpTypeSampler, .{ .id_result = result_id }); |
| 397 | break :blk result_id; |
| 398 | }, |
| 399 | .OpTypeSampledImage => blk: { |
| 400 | const image_type = try self.resolveRefId(operands[1].ref_id); |
| 401 | const result_id = self.spv.allocId(); |
| 402 | try section.emit(self.gpa, .OpTypeSampledImage, .{ .id_result = result_id, .image_type = image_type }); |
| 403 | break :blk result_id; |
| 404 | }, |
| 371 | 405 | .OpTypeFunction => blk: { |
| 372 | 406 | const param_operands = operands[2..]; |
| 373 | 407 | const return_type = try self.resolveRefId(operands[1].ref_id); |
| ... | ... | @@ -406,18 +440,18 @@ fn processGenericInstruction(self: *Assembler) !?AsmValue { |
| 406 | 440 | else => switch (self.inst.opcode) { |
| 407 | 441 | .OpEntryPoint => unreachable, |
| 408 | 442 | .OpExecutionMode, .OpExecutionModeId => &self.spv.sections.execution_modes, |
| 409 | | .OpVariable => switch (@as(spec.StorageClass, @enumFromInt(operands[2].value))) { |
| 410 | | .Function => &self.func.prologue, |
| 411 | | .Input, .Output => section: { |
| 412 | | maybe_spv_decl_index = try self.spv.allocDecl(.global); |
| 413 | | try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {}); |
| 414 | | // TODO: In theory this can be non-empty if there is an initializer which depends on another global... |
| 415 | | try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{}); |
| 443 | .OpVariable => section: { |
| 444 | const storage_class: spec.StorageClass = @enumFromInt(operands[2].value); |
| 445 | if (storage_class == .Function) break :section &self.func.prologue; |
| 446 | maybe_spv_decl_index = try self.spv.allocDecl(.global); |
| 447 | if (self.spv.version.minor < 4 and storage_class != .Input and storage_class != .Output) { |
| 448 | // Before version 1.4, the interface’s storage classes are limited to the Input and Output |
| 416 | 449 | break :section &self.spv.sections.types_globals_constants; |
| 417 | | }, |
| 418 | | // These don't need to be marked in the dependency system. |
| 419 | | // Probably we should add them anyway, then filter out PushConstant globals. |
| 420 | | else => &self.spv.sections.types_globals_constants, |
| 450 | } |
| 451 | try self.func.decl_deps.put(self.spv.gpa, maybe_spv_decl_index.?, {}); |
| 452 | // TODO: In theory this can be non-empty if there is an initializer which depends on another global... |
| 453 | try self.spv.declareDeclDeps(maybe_spv_decl_index.?, &.{}); |
| 454 | break :section &self.spv.sections.types_globals_constants; |
| 421 | 455 | }, |
| 422 | 456 | // Default case - to be worked out further. |
| 423 | 457 | else => &self.func.body, |