[IR] adding OpNot and fixing access chain handling
This commit is contained in:
@@ -34,6 +34,11 @@ pub const ValidationError = error{
|
||||
WrongReturnType,
|
||||
};
|
||||
|
||||
const IntegerShape = struct {
|
||||
bits: u16,
|
||||
components: u8,
|
||||
};
|
||||
|
||||
pub const Error = ValidationError || std.mem.Allocator.Error;
|
||||
|
||||
pub fn validate(module: *const module_ir.Module) Error!void {
|
||||
@@ -227,13 +232,37 @@ fn validateOperation(module: *const module_ir.Module, function_id: ids.FunctionI
|
||||
|
||||
switch (instruction.operation) {
|
||||
.unary => |op| {
|
||||
const operand_type = try operandType(module, function_id, op.operand);
|
||||
const operand_type =
|
||||
try operandType(module, function_id, op.operand);
|
||||
|
||||
if (result_type == null)
|
||||
return ValidationError.WrongResultPresence;
|
||||
const result =
|
||||
result_type orelse return ValidationError.WrongResultPresence;
|
||||
|
||||
if (result_type.? != operand_type)
|
||||
switch (op.opcode) {
|
||||
.bitwise_not => {
|
||||
if (!isIntegerScalarOrVector(module, operand_type))
|
||||
return ValidationError.WrongOperandType;
|
||||
|
||||
if (!isIntegerScalarOrVector(module, result))
|
||||
return ValidationError.WrongResultType;
|
||||
|
||||
if (!haveSameIntegerShape(module, operand_type, result))
|
||||
return ValidationError.WrongResultType;
|
||||
},
|
||||
|
||||
.logical_not => {
|
||||
if (!isBoolean(module, operand_type))
|
||||
return ValidationError.WrongOperandType;
|
||||
|
||||
if (!isBoolean(module, result))
|
||||
return ValidationError.WrongResultType;
|
||||
},
|
||||
|
||||
.negate => {
|
||||
if (result != operand_type)
|
||||
return ValidationError.WrongResultType;
|
||||
},
|
||||
}
|
||||
},
|
||||
.binary => |op| {
|
||||
const lhs_type = try operandType(module, function_id, op.lhs);
|
||||
@@ -533,6 +562,46 @@ fn isArrayLengthResultType(module: *const module_ir.Module, type_id: ids.TypeId)
|
||||
};
|
||||
}
|
||||
|
||||
fn integerShape(module: *const module_ir.Module, type_id: ids.TypeId) ?IntegerShape {
|
||||
const ty = module.types.get(type_id) orelse return null;
|
||||
|
||||
return switch (ty.*) {
|
||||
.integer => |integer| .{
|
||||
.bits = integer.bits,
|
||||
.components = 1,
|
||||
},
|
||||
|
||||
.vector => |vector| blk: {
|
||||
const element =
|
||||
module.types.get(vector.element_type) orelse return null;
|
||||
|
||||
const integer = switch (element.*) {
|
||||
.integer => |integer| integer,
|
||||
else => return null,
|
||||
};
|
||||
|
||||
break :blk .{
|
||||
.bits = integer.bits,
|
||||
.components = vector.length,
|
||||
};
|
||||
},
|
||||
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
fn isIntegerScalarOrVector(module: *const module_ir.Module, type_id: ids.TypeId) bool {
|
||||
return integerShape(module, type_id) != null;
|
||||
}
|
||||
|
||||
fn haveSameIntegerShape(module: *const module_ir.Module, lhs: ids.TypeId, rhs: ids.TypeId) bool {
|
||||
const lhs_shape = integerShape(module, lhs) orelse return false;
|
||||
const rhs_shape = integerShape(module, rhs) orelse return false;
|
||||
|
||||
return lhs_shape.bits == rhs_shape.bits and
|
||||
lhs_shape.components == rhs_shape.components;
|
||||
}
|
||||
|
||||
fn targetsBlock(terminator: module_ir.Terminator, target: ids.BlockId) bool {
|
||||
return switch (terminator) {
|
||||
.branch => |edge| edge.target == target,
|
||||
|
||||
@@ -69,6 +69,16 @@ const BufferAddress = struct {
|
||||
pointee_type: u32,
|
||||
};
|
||||
|
||||
const CompositeAddress = struct {
|
||||
root: union(enum) {
|
||||
local: usize,
|
||||
interface: ir.id.InterfaceVariableId,
|
||||
},
|
||||
root_type: u32,
|
||||
pointee_type: u32,
|
||||
indices: []const u32,
|
||||
};
|
||||
|
||||
const LocalVariable = struct {
|
||||
spv_id: u32,
|
||||
type: ir.id.TypeId,
|
||||
@@ -99,6 +109,7 @@ const Context = struct {
|
||||
interfaces: []?ir.id.InterfaceVariableId,
|
||||
resources: []?ir.id.ResourceId,
|
||||
buffer_addresses: []?BufferAddress,
|
||||
composite_addresses: []?CompositeAddress,
|
||||
member_offsets: std.ArrayList(MemberOffset) = .empty,
|
||||
phi_infos: std.ArrayList(PhiInfo) = .empty,
|
||||
|
||||
@@ -391,6 +402,11 @@ const Context = struct {
|
||||
return self.buffer_addresses[index];
|
||||
}
|
||||
|
||||
fn compositeAddress(self: *const Context, spv_id: u32) TranslationError!?CompositeAddress {
|
||||
const index = try self.idIndex(spv_id);
|
||||
return self.composite_addresses[index];
|
||||
}
|
||||
|
||||
fn localIndex(self: *const Context, spv_id: u32) TranslationError!?usize {
|
||||
const index = try self.idIndex(spv_id);
|
||||
return self.local_indices[index];
|
||||
@@ -437,6 +453,7 @@ pub fn instantiate(allocator: std.mem.Allocator, source: *const SourceModule, op
|
||||
.interfaces = try allocOptional(ir.id.InterfaceVariableId, scratch, bound),
|
||||
.resources = try allocOptional(ir.id.ResourceId, scratch, bound),
|
||||
.buffer_addresses = try allocOptional(BufferAddress, scratch, bound),
|
||||
.composite_addresses = try allocOptional(CompositeAddress, scratch, bound),
|
||||
.local_indices = try allocOptional(usize, scratch, bound),
|
||||
.block_local_inputs = try allocOptional(ir.id.ValueId, scratch, 0),
|
||||
.block_local_outputs = try allocOptional(ir.id.ValueId, scratch, 0),
|
||||
@@ -992,6 +1009,23 @@ fn translateInstruction(context: *Context, block: ir.id.BlockId, instruction: Pa
|
||||
},
|
||||
}, context.nameOf(operands[1]))).?;
|
||||
try context.setValue(operands[1], result);
|
||||
} else if (try context.compositeAddress(operands[2])) |address| {
|
||||
const composite = switch (address.root) {
|
||||
.local => |local_index| context.current_locals[local_index] orelse return TranslationError.InvalidInstruction,
|
||||
.interface => |variable| (try context.builder.appendInstruction(
|
||||
block,
|
||||
try context.translateType(address.root_type),
|
||||
.{ .load_interface = .{ .variable = variable } },
|
||||
null,
|
||||
)).?,
|
||||
};
|
||||
const result = (try context.builder.appendInstruction(block, result_type, .{
|
||||
.composite_extract = .{
|
||||
.composite = composite,
|
||||
.indices = address.indices,
|
||||
},
|
||||
}, context.nameOf(operands[1]))).?;
|
||||
try context.setValue(operands[1], result);
|
||||
} else {
|
||||
const result = (try context.builder.appendInstruction(block, result_type, .{
|
||||
.load_interface = .{ .variable = try context.interfaceVariable(operands[2]) },
|
||||
@@ -1016,6 +1050,8 @@ fn translateInstruction(context: *Context, block: ir.id.BlockId, instruction: Pa
|
||||
.value = value,
|
||||
},
|
||||
}, null);
|
||||
} else if (try context.compositeAddress(operands[0]) != null) {
|
||||
return TranslationError.UnsupportedOpcode;
|
||||
} else {
|
||||
_ = try context.builder.appendInstruction(block, null, .{
|
||||
.store_interface = .{
|
||||
@@ -1029,15 +1065,32 @@ fn translateInstruction(context: *Context, block: ir.id.BlockId, instruction: Pa
|
||||
.s_negate,
|
||||
.f_negate,
|
||||
.logical_not,
|
||||
.not,
|
||||
=> {
|
||||
try expectOperandCount(operands, 3);
|
||||
|
||||
const result = (try context.builder.appendInstruction(block, try context.translateType(operands[0]), .{
|
||||
const opcode: ir.instruction.UnaryOpcode = switch (instruction.opcode) {
|
||||
.s_negate,
|
||||
.f_negate,
|
||||
=> .negate,
|
||||
|
||||
.logical_not => .logical_not,
|
||||
.not => .bitwise_not,
|
||||
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const result = (try context.builder.appendInstruction(
|
||||
block,
|
||||
try context.translateType(operands[0]),
|
||||
.{
|
||||
.unary = .{
|
||||
.opcode = if (instruction.opcode == .logical_not) .logical_not else .negate,
|
||||
.opcode = opcode,
|
||||
.operand = try context.resolveValue(operands[2]),
|
||||
},
|
||||
}, context.nameOf(operands[1]))).?;
|
||||
},
|
||||
context.nameOf(operands[1]),
|
||||
)).?;
|
||||
|
||||
try context.setValue(operands[1], result);
|
||||
},
|
||||
@@ -1064,11 +1117,12 @@ fn translateInstruction(context: *Context, block: ir.id.BlockId, instruction: Pa
|
||||
=> {
|
||||
try expectOperandCount(operands, 4);
|
||||
|
||||
const result = (try context.builder.appendInstruction(block, try context.translateType(operands[0]), .{
|
||||
const result_type = try context.translateType(operands[0]);
|
||||
const result = (try context.builder.appendInstruction(block, result_type, .{
|
||||
.binary = .{
|
||||
.opcode = translateBinaryOpcode(instruction.opcode),
|
||||
.lhs = try context.resolveValue(operands[2]),
|
||||
.rhs = try context.resolveValue(operands[3]),
|
||||
.lhs = try coerceIntegerSignedness(context, block, try context.resolveValue(operands[2]), result_type),
|
||||
.rhs = try coerceIntegerSignedness(context, block, try context.resolveValue(operands[3]), result_type),
|
||||
},
|
||||
}, context.nameOf(operands[1]))).?;
|
||||
|
||||
@@ -1156,9 +1210,9 @@ fn translateInstruction(context: *Context, block: ir.id.BlockId, instruction: Pa
|
||||
|
||||
else => {
|
||||
if (std.enums.tagName(spirv.Opcode, instruction.opcode)) |opcode| {
|
||||
std.log.scoped(.spirv_translator).err("unsupported opcode {s}", .{opcode});
|
||||
std.log.scoped(.spirv_translator).err("unsupported opcode: '{s}'", .{opcode});
|
||||
} else {
|
||||
std.log.scoped(.spirv_translator).err("unsupported opcode {d}", .{instruction.opcode});
|
||||
std.log.scoped(.spirv_translator).err("unsupported opcode: {d}", .{instruction.opcode});
|
||||
}
|
||||
return TranslationError.UnsupportedOpcode;
|
||||
},
|
||||
@@ -1169,7 +1223,13 @@ fn translateAccessChain(context: *Context, block: ir.id.BlockId, operands: []con
|
||||
if (operands.len < 4)
|
||||
return TranslationError.InvalidInstruction;
|
||||
|
||||
const base = (try context.bufferAddress(operands[2])) orelse return TranslationError.UnsupportedOpcode;
|
||||
if (try context.bufferAddress(operands[2])) |base|
|
||||
return translateBufferAccessChain(context, block, operands, base);
|
||||
|
||||
try translateCompositeAccessChain(context, operands);
|
||||
}
|
||||
|
||||
fn translateBufferAccessChain(context: *Context, block: ir.id.BlockId, operands: []const u32, base: BufferAddress) !void {
|
||||
var current_type = base.pointee_type;
|
||||
var byte_offset = base.byte_offset;
|
||||
|
||||
@@ -1189,7 +1249,7 @@ fn translateAccessChain(context: *Context, block: ir.id.BlockId, operands: []con
|
||||
current_type = type_definition.operands[member + 1];
|
||||
},
|
||||
.type_array, .type_runtime_array => {
|
||||
try expectOperandCount(type_definition.operands, 3);
|
||||
try expectOperandCount(type_definition.operands, if (type_definition.opcode == .type_array) 3 else 2);
|
||||
const stride = context.decorations[try context.idIndex(current_type)].array_stride orelse return TranslationError.InvalidInstruction;
|
||||
const index = try unsignedOffsetValue(context, block, index_id);
|
||||
const stride_value = try context.builder.internConstant(try unsigned32Type(context), .{ .integer_bits = stride });
|
||||
@@ -1224,6 +1284,81 @@ fn translateAccessChain(context: *Context, block: ir.id.BlockId, operands: []con
|
||||
};
|
||||
}
|
||||
|
||||
fn translateCompositeAccessChain(context: *Context, operands: []const u32) !void {
|
||||
var address: CompositeAddress = if (try context.compositeAddress(operands[2])) |base|
|
||||
base
|
||||
else if (try context.localIndex(operands[2])) |local_index| blk: {
|
||||
const pointee_type = try variablePointeeType(context, operands[2]);
|
||||
break :blk .{
|
||||
.root = .{ .local = local_index },
|
||||
.root_type = pointee_type,
|
||||
.pointee_type = pointee_type,
|
||||
.indices = &.{},
|
||||
};
|
||||
} else blk: {
|
||||
const pointee_type = try variablePointeeType(context, operands[2]);
|
||||
break :blk .{
|
||||
.root = .{ .interface = try context.interfaceVariable(operands[2]) },
|
||||
.root_type = pointee_type,
|
||||
.pointee_type = pointee_type,
|
||||
.indices = &.{},
|
||||
};
|
||||
};
|
||||
|
||||
var indices = std.ArrayList(u32).empty;
|
||||
defer indices.deinit(context.scratch);
|
||||
try indices.appendSlice(context.scratch, address.indices);
|
||||
|
||||
for (operands[3..]) |index_id| {
|
||||
const type_definition = context.type_defs[try context.idIndex(address.pointee_type)] orelse return TranslationError.MissingDefinition;
|
||||
const index = try constantIndex(context, index_id);
|
||||
address.pointee_type = switch (type_definition.opcode) {
|
||||
.type_struct => blk: {
|
||||
if (index + 1 >= type_definition.operands.len)
|
||||
return TranslationError.InvalidInstruction;
|
||||
break :blk type_definition.operands[index + 1];
|
||||
},
|
||||
.type_vector, .type_matrix => blk: {
|
||||
try expectOperandCount(type_definition.operands, 3);
|
||||
if (index >= type_definition.operands[2])
|
||||
return TranslationError.InvalidInstruction;
|
||||
break :blk type_definition.operands[1];
|
||||
},
|
||||
.type_array => blk: {
|
||||
try expectOperandCount(type_definition.operands, 3);
|
||||
const length = try constantIndex(context, type_definition.operands[2]);
|
||||
if (index >= length)
|
||||
return TranslationError.InvalidInstruction;
|
||||
break :blk type_definition.operands[1];
|
||||
},
|
||||
else => return TranslationError.UnsupportedType,
|
||||
};
|
||||
try indices.append(context.scratch, index);
|
||||
}
|
||||
|
||||
const result_pointer = context.type_defs[try context.idIndex(operands[0])] orelse return TranslationError.MissingDefinition;
|
||||
if (result_pointer.opcode != .type_pointer)
|
||||
return TranslationError.InvalidInstruction;
|
||||
try expectOperandCount(result_pointer.operands, 3);
|
||||
if (result_pointer.operands[2] != address.pointee_type)
|
||||
return TranslationError.InvalidInstruction;
|
||||
|
||||
const result_index = try context.idIndex(operands[1]);
|
||||
if (context.composite_addresses[result_index] != null)
|
||||
return TranslationError.DuplicateId;
|
||||
address.indices = try context.scratch.dupe(u32, indices.items);
|
||||
context.composite_addresses[result_index] = address;
|
||||
}
|
||||
|
||||
fn variablePointeeType(context: *Context, spv_id: u32) !u32 {
|
||||
const variable = context.variable_defs[try context.idIndex(spv_id)] orelse return TranslationError.MissingDefinition;
|
||||
const pointer = context.type_defs[try context.idIndex(variable.operands[0])] orelse return TranslationError.MissingDefinition;
|
||||
if (pointer.opcode != .type_pointer)
|
||||
return TranslationError.InvalidInstruction;
|
||||
try expectOperandCount(pointer.operands, 3);
|
||||
return pointer.operands[2];
|
||||
}
|
||||
|
||||
fn translateArrayLength(context: *Context, block: ir.id.BlockId, operands: []const u32) !void {
|
||||
try expectOperandCount(operands, 4);
|
||||
|
||||
@@ -1309,6 +1444,40 @@ fn unsigned32Type(context: *Context) !ir.id.TypeId {
|
||||
return context.builder.internType(.{ .integer = .{ .bits = 32, .signedness = .unsigned } });
|
||||
}
|
||||
|
||||
fn coerceIntegerSignedness(context: *Context, block: ir.id.BlockId, value: ir.id.ValueId, target_type: ir.id.TypeId) !ir.id.ValueId {
|
||||
const source_type = context.module.typeOf(value) orelse return TranslationError.InvalidId;
|
||||
if (source_type == target_type)
|
||||
return value;
|
||||
|
||||
const source_shape = integerTypeShape(context, source_type) orelse return TranslationError.InvalidInstruction;
|
||||
const target_shape = integerTypeShape(context, target_type) orelse return TranslationError.InvalidInstruction;
|
||||
if (!std.meta.eql(source_shape, target_shape))
|
||||
return TranslationError.InvalidInstruction;
|
||||
|
||||
return (try context.builder.appendInstruction(block, target_type, .{ .bitcast = value }, null)).?;
|
||||
}
|
||||
|
||||
const IntegerTypeShape = struct {
|
||||
bits: u16,
|
||||
components: u8,
|
||||
};
|
||||
|
||||
fn integerTypeShape(context: *const Context, type_id: ir.id.TypeId) ?IntegerTypeShape {
|
||||
const ty = context.module.types.get(type_id) orelse return null;
|
||||
return switch (ty.*) {
|
||||
.integer => |integer| .{ .bits = integer.bits, .components = 1 },
|
||||
.vector => |vector| blk: {
|
||||
const element_type = context.module.types.get(vector.element_type) orelse return null;
|
||||
const integer = switch (element_type.*) {
|
||||
.integer => |integer| integer,
|
||||
else => return null,
|
||||
};
|
||||
break :blk .{ .bits = integer.bits, .components = vector.length };
|
||||
},
|
||||
else => null,
|
||||
};
|
||||
}
|
||||
|
||||
fn unsignedOffsetValue(context: *Context, block: ir.id.BlockId, spv_id: u32) !ir.id.ValueId {
|
||||
const value = try context.resolveValue(spv_id);
|
||||
const type_id = context.module.typeOf(value) orelse return TranslationError.InvalidId;
|
||||
@@ -1795,6 +1964,56 @@ test "SPIR-V: decorated vertex interfaces and load-store operations" {
|
||||
try std.testing.expect(std.mem.indexOf(u8, text, "store_interface @out_color") != null);
|
||||
}
|
||||
|
||||
test "SPIR-V: access chains into interface vectors and promoted local vectors" {
|
||||
const assembly =
|
||||
\\OpCapability Shader
|
||||
\\OpMemoryModel Logical GLSL450
|
||||
\\OpEntryPoint GLCompute %main "main" %global_id
|
||||
\\OpExecutionMode %main LocalSize 1 1 1
|
||||
\\OpName %global_y "global_y"
|
||||
\\OpName %local_z "local_z"
|
||||
\\OpName %signed_one "signed_one"
|
||||
\\OpDecorate %global_id BuiltIn GlobalInvocationId
|
||||
\\%void = OpTypeVoid
|
||||
\\%uint = OpTypeInt 32 0
|
||||
\\%int = OpTypeInt 32 1
|
||||
\\%vec3 = OpTypeVector %uint 3
|
||||
\\%ptr_input_vec3 = OpTypePointer Input %vec3
|
||||
\\%ptr_input_uint = OpTypePointer Input %uint
|
||||
\\%ptr_function_vec3 = OpTypePointer Function %vec3
|
||||
\\%ptr_function_uint = OpTypePointer Function %uint
|
||||
\\%fn_void = OpTypeFunction %void
|
||||
\\%one = OpConstant %uint 1
|
||||
\\%two = OpConstant %uint 2
|
||||
\\%signed_one = OpConstant %int 1
|
||||
\\%global_id = OpVariable %ptr_input_vec3 Input
|
||||
\\%main = OpFunction %void None %fn_void
|
||||
\\ %entry = OpLabel
|
||||
\\ %local = OpVariable %ptr_function_vec3 Function
|
||||
\\ %global = OpLoad %vec3 %global_id
|
||||
\\ OpStore %local %global
|
||||
\\ %global_y_ptr = OpAccessChain %ptr_input_uint %global_id %one
|
||||
\\ %global_y = OpLoad %uint %global_y_ptr
|
||||
\\ %local_z_ptr = OpAccessChain %ptr_function_uint %local %two
|
||||
\\ %local_z = OpLoad %uint %local_z_ptr
|
||||
\\ %sum = OpIAdd %uint %global_y %local_z
|
||||
\\ %increment = OpIAdd %uint %sum %signed_one
|
||||
\\ OpReturn
|
||||
\\OpFunctionEnd
|
||||
;
|
||||
const words = try assembleSpirv(std.testing.allocator, assembly);
|
||||
defer std.testing.allocator.free(words);
|
||||
|
||||
var module = try translate(std.testing.allocator, words, .{ .entry_point = "main" });
|
||||
defer module.deinit();
|
||||
|
||||
const text = try ir.printer.allocPrint(std.testing.allocator, &module);
|
||||
defer std.testing.allocator.free(text);
|
||||
try std.testing.expect(std.mem.indexOf(u8, text, "%global_y: u32 = composite_extract") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, text, "%local_z: u32 = composite_extract") != null);
|
||||
try std.testing.expect(std.mem.indexOf(u8, text, "bitcast %signed_one") != null);
|
||||
}
|
||||
|
||||
test "SPIR-V: storage buffers and promoted function locals" {
|
||||
const assembly =
|
||||
\\OpCapability Shader
|
||||
|
||||
@@ -6,6 +6,69 @@ const PciInfo = struct {
|
||||
|
||||
/// Not a hashmap as they need runtime allocations
|
||||
pub const map = [_]PciInfo{
|
||||
.{ .id = 0x0a02, .name = "Intel(R) HD Graphics (Haswell-ULT GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0a06, .name = "Intel(R) HD Graphics (Haswell-ULT GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0a0a, .name = "Intel(R) HD Graphics (Haswell-ULT GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0a0b, .name = "Intel(R) HD Graphics (Haswell-ULT GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0a0e, .name = "Intel(R) HD Graphics (Haswell-ULX GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0402, .name = "Intel(R) HD Graphics (Haswell GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0406, .name = "Intel(R) HD Graphics (Haswell GT1)", .is_discrete = false },
|
||||
.{ .id = 0x040a, .name = "Intel(R) HD Graphics (Haswell GT1)", .is_discrete = false },
|
||||
.{ .id = 0x040b, .name = "Intel(R) HD Graphics (Haswell GT1)", .is_discrete = false },
|
||||
.{ .id = 0x040e, .name = "Intel(R) HD Graphics (Haswell GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0c02, .name = "Intel(R) HD Graphics (Haswell-SDV GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0c06, .name = "Intel(R) HD Graphics (Haswell-SDV GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0c0a, .name = "Intel(R) HD Graphics (Haswell-SDV GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0c0b, .name = "Intel(R) HD Graphics (Haswell-SDV GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0c0e, .name = "Intel(R) HD Graphics (Haswell-SDV GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0d02, .name = "Intel(R) HD Graphics (Haswell-CRW GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0d06, .name = "Intel(R) HD Graphics (Haswell-CRW GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0d0a, .name = "Intel(R) HD Graphics (Haswell-CRW GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0d0b, .name = "Intel(R) HD Graphics (Haswell-CRW GT1)", .is_discrete = false },
|
||||
.{ .id = 0x0d0e, .name = "Intel(R) HD Graphics (Haswell-CRW GT1)", .is_discrete = false },
|
||||
|
||||
.{ .id = 0x0a12, .name = "Intel(R) HD Graphics (Haswell-ULT GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0a16, .name = "Intel(R) HD Graphics 4400 (Haswell-ULT GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0a1a, .name = "Intel(R) HD Graphics (Haswell-ULT GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0a1b, .name = "Intel(R) HD Graphics (Haswell-ULT GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0a1e, .name = "Intel(R) HD Graphics 4200 (Haswell-ULX GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0412, .name = "Intel(R) HD Graphics 4600 (Haswell GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0416, .name = "Intel(R) HD Graphics 4600 (Haswell GT2)", .is_discrete = false },
|
||||
.{ .id = 0x041a, .name = "Intel(R) HD Graphics P4600/P4700 (Haswell GT2)", .is_discrete = false },
|
||||
.{ .id = 0x041b, .name = "Intel(R) HD Graphics (Haswell GT2)", .is_discrete = false },
|
||||
.{ .id = 0x041e, .name = "Intel(R) HD Graphics 4400 (Haswell GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0c12, .name = "Intel(R) HD Graphics (Haswell-SDV GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0c16, .name = "Intel(R) HD Graphics (Haswell-SDV GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0c1a, .name = "Intel(R) HD Graphics (Haswell-SDV GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0c1b, .name = "Intel(R) HD Graphics (Haswell-SDV GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0c1e, .name = "Intel(R) HD Graphics (Haswell-SDV GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0d12, .name = "Intel(R) HD Graphics 4600 (Haswell-CRW GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0d16, .name = "Intel(R) HD Graphics (Haswell-CRW GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0d1a, .name = "Intel(R) HD Graphics (Haswell-CRW GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0d1b, .name = "Intel(R) HD Graphics (Haswell-CRW GT2)", .is_discrete = false },
|
||||
.{ .id = 0x0d1e, .name = "Intel(R) HD Graphics (Haswell-CRW GT2)", .is_discrete = false },
|
||||
|
||||
.{ .id = 0x0a22, .name = "Intel(R) HD Graphics (Haswell-ULT GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0a26, .name = "Intel(R) HD Graphics 5000 (Haswell-ULT GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0a2a, .name = "Intel(R) HD Graphics (Haswell-ULT GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0a2b, .name = "Intel(R) HD Graphics (Haswell-ULT GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0a2e, .name = "Intel(R) Iris(R) Graphics 5100 (Haswell-ULT GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0422, .name = "Intel(R) HD Graphics (Haswell GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0426, .name = "Intel(R) HD Graphics (Haswell GT3)", .is_discrete = false },
|
||||
.{ .id = 0x042a, .name = "Intel(R) HD Graphics (Haswell GT3)", .is_discrete = false },
|
||||
.{ .id = 0x042b, .name = "Intel(R) HD Graphics (Haswell GT3)", .is_discrete = false },
|
||||
.{ .id = 0x042e, .name = "Intel(R) HD Graphics (Haswell GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0c22, .name = "Intel(R) HD Graphics (Haswell-SDV GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0c26, .name = "Intel(R) HD Graphics (Haswell-SDV GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0c2a, .name = "Intel(R) HD Graphics (Haswell-SDV GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0c2b, .name = "Intel(R) HD Graphics (Haswell-SDV GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0c2e, .name = "Intel(R) HD Graphics (Haswell-SDV GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0d22, .name = "Intel(R) Iris(R) Pro Graphics 5200 (Haswell-CRW GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0d26, .name = "Intel(R) Iris(R) Pro Graphics P5200 (Haswell-CRW GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0d2a, .name = "Intel(R) HD Graphics (Haswell-CRW GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0d2b, .name = "Intel(R) HD Graphics (Haswell-CRW GT3)", .is_discrete = false },
|
||||
.{ .id = 0x0d2e, .name = "Intel(R) HD Graphics (Haswell-CRW GT3)", .is_discrete = false },
|
||||
|
||||
.{ .id = 0x1602, .name = "Intel(R) HD Graphics (Broadwell-U)", .is_discrete = false },
|
||||
.{ .id = 0x1606, .name = "Intel(R) HD Graphics (Broadwell-U GT1)", .is_discrete = false },
|
||||
.{ .id = 0x160a, .name = "Intel(R) HD Graphics (Broadwell-U)", .is_discrete = false },
|
||||
|
||||
Reference in New Issue
Block a user