case vtn_value_type_ssa:
return val->ssa;
+ case vtn_value_type_pointer:
+ assert(val->pointer->ptr_type && val->pointer->ptr_type->type);
+ struct vtn_ssa_value *ssa =
+ vtn_create_ssa_value(b, val->pointer->ptr_type->type);
+ ssa->def = vtn_pointer_to_ssa(b, val->pointer);
+ return ssa;
+
default:
unreachable("Invalid type for an SSA value");
}
if (strcmp((const char *)&w[2], "GLSL.std.450") == 0) {
val->ext_handler = vtn_handle_glsl450_instruction;
} else {
- assert(!"Unsupported extension");
+ unreachable("Unsupported extension");
}
break;
}
switch (dec->decoration) {
case SpvDecorationArrayStride:
+ assert(type->base_type == vtn_base_type_matrix ||
+ type->base_type == vtn_base_type_array ||
+ type->base_type == vtn_base_type_pointer);
type->stride = dec->literals[0];
break;
case SpvDecorationBlock:
+ assert(type->base_type == vtn_base_type_struct);
type->block = true;
break;
case SpvDecorationBufferBlock:
+ assert(type->base_type == vtn_base_type_struct);
type->buffer_block = true;
break;
case SpvDecorationGLSLShared:
case SpvImageFormatRg32ui: return 0x823C; /* GL_RG32UI */
case SpvImageFormatRg16ui: return 0x823A; /* GL_RG16UI */
case SpvImageFormatRg8ui: return 0x8238; /* GL_RG8UI */
- case SpvImageFormatR16ui: return 0x823A; /* GL_RG16UI */
+ case SpvImageFormatR16ui: return 0x8234; /* GL_R16UI */
case SpvImageFormatR8ui: return 0x8232; /* GL_R8UI */
default:
- assert(!"Invalid image format");
+ unreachable("Invalid image format");
return 0;
}
}
vtn_value(b, w[3], vtn_value_type_type)->type;
val->type->base_type = vtn_base_type_pointer;
- val->type->type = NULL;
val->type->storage_class = storage_class;
val->type->deref = deref_type;
+
+ if (storage_class == SpvStorageClassUniform ||
+ storage_class == SpvStorageClassStorageBuffer) {
+ /* These can actually be stored to nir_variables and used as SSA
+ * values so they need a real glsl_type.
+ */
+ val->type->type = glsl_vector_type(GLSL_TYPE_UINT, 2);
+ }
break;
}
else if (dim == GLSL_SAMPLER_DIM_SUBPASS)
dim = GLSL_SAMPLER_DIM_SUBPASS_MS;
else
- assert(!"Unsupported multisampled image type");
+ unreachable("Unsupported multisampled image type");
}
val->type->image_format = translate_image_format(format);
val->type->type = glsl_image_type(dim, is_array,
glsl_get_base_type(sampled_type));
} else {
- assert(!"We need to know if the image will be sampled");
+ unreachable("We need to know if the image will be sampled");
}
break;
}
break;
case SpvOpConstantSampler:
- assert(!"OpConstantSampler requires Kernel Capability");
+ unreachable("OpConstantSampler requires Kernel Capability");
break;
default:
vtn_handle_function_call(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
{
+ struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type;
struct nir_function *callee =
vtn_value(b, w[3], vtn_value_type_function)->func->impl->function;
for (unsigned i = 0; i < call->num_params; i++) {
unsigned arg_id = w[4 + i];
struct vtn_value *arg = vtn_untyped_value(b, arg_id);
- if (arg->value_type == vtn_value_type_pointer) {
+ if (arg->value_type == vtn_value_type_pointer &&
+ arg->pointer->ptr_type->type == NULL) {
nir_deref_var *d = vtn_pointer_to_deref(b, arg->pointer);
call->params[i] = nir_deref_var_clone(d, call);
} else {
}
nir_variable *out_tmp = NULL;
+ assert(res_type->type == callee->return_type);
if (!glsl_type_is_void(callee->return_type)) {
out_tmp = nir_local_variable_create(b->impl, callee->return_type,
"out_tmp");
if (glsl_type_is_void(callee->return_type)) {
vtn_push_value(b, w[2], vtn_value_type_undef);
} else {
- struct vtn_value *retval = vtn_push_value(b, w[2], vtn_value_type_ssa);
- retval->ssa = vtn_local_load(b, call->return_deref);
+ vtn_push_ssa(b, w[2], res_type, vtn_local_load(b, call->return_deref));
}
}
intrin->src[2] = nir_src_for_ssa(vtn_ssa_value(b, w[3])->def);
break;
+ case SpvOpAtomicCompareExchange:
case SpvOpAtomicIIncrement:
case SpvOpAtomicIDecrement:
case SpvOpAtomicExchange:
case SpvOpAtomicIAdd:
+ case SpvOpAtomicISub:
case SpvOpAtomicSMin:
case SpvOpAtomicUMin:
case SpvOpAtomicSMax:
case SpvExecutionModeOutputTriangleStrip:
return 5; /* GL_TRIANGLE_STRIP */
default:
- assert(!"Invalid primitive type");
+ unreachable("Invalid primitive type");
return 4;
}
}
case SpvExecutionModeInputTrianglesAdjacency:
return 6;
default:
- assert(!"Invalid GS input mode");
+ unreachable("Invalid GS input mode");
return 0;
}
}
case SpvCapabilitySampled1D:
case SpvCapabilityImage1D:
case SpvCapabilitySampledCubeArray:
+ case SpvCapabilityImageCubeArray:
case SpvCapabilitySampledBuffer:
case SpvCapabilityImageBuffer:
case SpvCapabilityImageQuery:
case SpvCapabilityAtomicStorage:
case SpvCapabilityInt16:
case SpvCapabilityStorageImageMultisample:
- case SpvCapabilityImageCubeArray:
case SpvCapabilityInt8:
case SpvCapabilitySparseResidency:
case SpvCapabilityMinLod:
spv_check_supported(multiview, cap);
break;
+ case SpvCapabilityVariablePointersStorageBuffer:
+ case SpvCapabilityVariablePointers:
+ spv_check_supported(variable_pointers, cap);
+ break;
+
default:
unreachable("Unhandled capability");
}
break;
case SpvExecutionModeEarlyFragmentTests:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
+ assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
b->shader->info.fs.early_fragment_tests = true;
break;
case SpvExecutionModeInvocations:
- assert(b->shader->stage == MESA_SHADER_GEOMETRY);
+ assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);
b->shader->info.gs.invocations = MAX2(1, mode->literals[0]);
break;
case SpvExecutionModeDepthReplacing:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
+ assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_ANY;
break;
case SpvExecutionModeDepthGreater:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
+ assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_GREATER;
break;
case SpvExecutionModeDepthLess:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
+ assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_LESS;
break;
case SpvExecutionModeDepthUnchanged:
- assert(b->shader->stage == MESA_SHADER_FRAGMENT);
+ assert(b->shader->info.stage == MESA_SHADER_FRAGMENT);
b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_UNCHANGED;
break;
case SpvExecutionModeLocalSize:
- assert(b->shader->stage == MESA_SHADER_COMPUTE);
+ assert(b->shader->info.stage == MESA_SHADER_COMPUTE);
b->shader->info.cs.local_size[0] = mode->literals[0];
b->shader->info.cs.local_size[1] = mode->literals[1];
b->shader->info.cs.local_size[2] = mode->literals[2];
break; /* Nothing to do with this */
case SpvExecutionModeOutputVertices:
- if (b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL) {
+ if (b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL) {
b->shader->info.tess.tcs_vertices_out = mode->literals[0];
} else {
- assert(b->shader->stage == MESA_SHADER_GEOMETRY);
+ assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);
b->shader->info.gs.vertices_out = mode->literals[0];
}
break;
case SpvExecutionModeInputTrianglesAdjacency:
case SpvExecutionModeQuads:
case SpvExecutionModeIsolines:
- if (b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL) {
+ if (b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL) {
b->shader->info.tess.primitive_mode =
gl_primitive_from_spv_execution_mode(mode->exec_mode);
} else {
- assert(b->shader->stage == MESA_SHADER_GEOMETRY);
+ assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);
b->shader->info.gs.vertices_in =
vertices_in_from_spv_execution_mode(mode->exec_mode);
}
case SpvExecutionModeOutputPoints:
case SpvExecutionModeOutputLineStrip:
case SpvExecutionModeOutputTriangleStrip:
- assert(b->shader->stage == MESA_SHADER_GEOMETRY);
+ assert(b->shader->info.stage == MESA_SHADER_GEOMETRY);
b->shader->info.gs.output_primitive =
gl_primitive_from_spv_execution_mode(mode->exec_mode);
break;
case SpvExecutionModeSpacingEqual:
- assert(b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL);
+ assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL);
b->shader->info.tess.spacing = TESS_SPACING_EQUAL;
break;
case SpvExecutionModeSpacingFractionalEven:
- assert(b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL);
+ assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL);
b->shader->info.tess.spacing = TESS_SPACING_FRACTIONAL_EVEN;
break;
case SpvExecutionModeSpacingFractionalOdd:
- assert(b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL);
+ assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL);
b->shader->info.tess.spacing = TESS_SPACING_FRACTIONAL_ODD;
break;
case SpvExecutionModeVertexOrderCw:
- assert(b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL);
- /* Vulkan's notion of CCW seems to match the hardware backends,
- * but be the opposite of OpenGL. Currently NIR follows GL semantics,
- * so we set it backwards here.
- */
- b->shader->info.tess.ccw = true;
+ assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL);
+ b->shader->info.tess.ccw = false;
break;
case SpvExecutionModeVertexOrderCcw:
- assert(b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL);
- /* Backwards; see above */
- b->shader->info.tess.ccw = false;
+ assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL);
+ b->shader->info.tess.ccw = true;
break;
case SpvExecutionModePointMode:
- assert(b->shader->stage == MESA_SHADER_TESS_CTRL ||
- b->shader->stage == MESA_SHADER_TESS_EVAL);
+ assert(b->shader->info.stage == MESA_SHADER_TESS_CTRL ||
+ b->shader->info.stage == MESA_SHADER_TESS_EVAL);
b->shader->info.tess.point_mode = true;
break;
break;
case SpvExecutionModeXfb:
- assert(!"Unhandled execution mode");
+ unreachable("Unhandled execution mode");
break;
case SpvExecutionModeVecTypeHint:
case SpvOpMemberDecorate:
case SpvOpGroupDecorate:
case SpvOpGroupMemberDecorate:
- assert(!"Invalid opcode types and variables section");
+ unreachable("Invalid opcode types and variables section");
break;
case SpvOpTypeVoid:
case SpvOpCopyMemory:
case SpvOpCopyMemorySized:
case SpvOpAccessChain:
+ case SpvOpPtrAccessChain:
case SpvOpInBoundsAccessChain:
case SpvOpArrayLength:
vtn_handle_variables(b, opcode, w, count);
break;
}
+ case SpvOpSelect: {
+ /* Handle OpSelect up-front here because it needs to be able to handle
+ * pointers and not just regular vectors and scalars.
+ */
+ struct vtn_type *res_type = vtn_value(b, w[1], vtn_value_type_type)->type;
+ struct vtn_ssa_value *ssa = vtn_create_ssa_value(b, res_type->type);
+ ssa->def = nir_bcsel(&b->nb, vtn_ssa_value(b, w[3])->def,
+ vtn_ssa_value(b, w[4])->def,
+ vtn_ssa_value(b, w[5])->def);
+ vtn_push_ssa(b, w[2], res_type, ssa);
+ break;
+ }
+
case SpvOpSNegate:
case SpvOpFNegate:
case SpvOpNot:
case SpvOpBitwiseOr:
case SpvOpBitwiseXor:
case SpvOpBitwiseAnd:
- case SpvOpSelect:
case SpvOpIEqual:
case SpvOpFOrdEqual:
case SpvOpFUnordEqual: