#include "tgsi/tgsi_parse.h"
#include "intel_winsys.h"
+#include "brw_defines.h" /* for SBE setup */
#include "shader/ilo_shader_internal.h"
#include "ilo_state.h"
break;
}
+ /* use PCB unless constant buffer 0 is not in user buffer */
+ if ((ilo->cbuf[info->type].enabled_mask & 0x1) &&
+ !ilo->cbuf[info->type].cso[0].user_buffer)
+ variant->use_pcb = false;
+ else
+ variant->use_pcb = true;
+
num_views = ilo->view[info->type].count;
assert(info->num_samplers <= num_views);
break;
}
+ variant->use_pcb = true;
+
variant->num_sampler_views = info->num_samplers;
for (i = 0; i < info->num_samplers; i++) {
if (info->shadow_samplers & (1 << i)) {
return sh;
}
+static void
+copy_so_info(struct ilo_shader *sh,
+ const struct pipe_stream_output_info *so_info)
+{
+ unsigned i, attr;
+
+ if (!so_info->num_outputs)
+ return;
+
+ sh->so_info = *so_info;
+
+ for (i = 0; i < so_info->num_outputs; i++) {
+ /* figure out which attribute is sourced */
+ for (attr = 0; attr < sh->out.count; attr++) {
+ const int reg_idx = sh->out.register_indices[attr];
+ if (reg_idx == so_info->output[i].register_index)
+ break;
+ }
+
+ if (attr < sh->out.count) {
+ sh->so_info.output[i].register_index = attr;
+ }
+ else {
+ assert(!"stream output an undefined register");
+ sh->so_info.output[i].register_index = 0;
+ }
+
+ /* PSIZE is at W channel */
+ if (sh->out.semantic_names[attr] == TGSI_SEMANTIC_PSIZE) {
+ assert(so_info->output[i].start_component == 0);
+ assert(so_info->output[i].num_components == 1);
+ sh->so_info.output[i].start_component = 3;
+ }
+ }
+}
+
/**
* Add a shader variant to the shader state.
*/
sh->variant = *variant;
+ copy_so_info(sh, &state->info.stream_output);
+
ilo_shader_state_add_shader(state, sh);
return sh;
shader = ilo_shader_state_create(precompile, PIPE_SHADER_VERTEX, state);
/* states used in ilo_shader_variant_init() */
- shader->info.non_orthogonal_states = ILO_DIRTY_VERTEX_SAMPLER_VIEWS |
- ILO_DIRTY_RASTERIZER;
+ shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_VS |
+ ILO_DIRTY_RASTERIZER |
+ ILO_DIRTY_CBUF;
return shader;
}
shader = ilo_shader_state_create(precompile, PIPE_SHADER_GEOMETRY, state);
/* states used in ilo_shader_variant_init() */
- shader->info.non_orthogonal_states = ILO_DIRTY_GEOMETRY_SAMPLER_VIEWS |
+ shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_GS |
ILO_DIRTY_VS |
- ILO_DIRTY_RASTERIZER;
+ ILO_DIRTY_RASTERIZER |
+ ILO_DIRTY_CBUF;
return shader;
}
shader = ilo_shader_state_create(precompile, PIPE_SHADER_FRAGMENT, state);
/* states used in ilo_shader_variant_init() */
- shader->info.non_orthogonal_states = ILO_DIRTY_FRAGMENT_SAMPLER_VIEWS |
+ shader->info.non_orthogonal_states = ILO_DIRTY_VIEW_FS |
ILO_DIRTY_RASTERIZER |
- ILO_DIRTY_FRAMEBUFFER;
+ ILO_DIRTY_FB |
+ ILO_DIRTY_CBUF;
return shader;
}
return (shader->shader != cur);
}
+static int
+route_attr(const int *semantics, const int *indices, int len,
+ int semantic, int index)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ if (semantics[i] == semantic && indices[i] == index)
+ return i;
+ }
+
+ /* failed to match for COLOR, try BCOLOR */
+ if (semantic == TGSI_SEMANTIC_COLOR) {
+ for (i = 0; i < len; i++) {
+ if (semantics[i] == TGSI_SEMANTIC_BCOLOR && indices[i] == index)
+ return i;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Select a routing for the given source shader and rasterizer state.
+ *
+ * \return true if a different routing is selected
+ */
+bool
+ilo_shader_select_kernel_routing(struct ilo_shader_state *shader,
+ const struct ilo_shader_state *source,
+ const struct ilo_rasterizer_state *rasterizer)
+{
+ const uint32_t sprite_coord_enable = rasterizer->state.sprite_coord_enable;
+ const bool light_twoside = rasterizer->state.light_twoside;
+ struct ilo_shader *kernel = shader->shader;
+ struct ilo_kernel_routing *routing = &kernel->routing;
+ const int *src_semantics, *src_indices;
+ int src_len, max_src_slot;
+ int dst_len, dst_slot;
+
+ /* we are constructing 3DSTATE_SBE here */
+ assert(shader->info.dev->gen >= ILO_GEN(6) &&
+ shader->info.dev->gen <= ILO_GEN(7.5));
+
+ assert(kernel);
+
+ if (source) {
+ assert(source->shader);
+ src_semantics = source->shader->out.semantic_names;
+ src_indices = source->shader->out.semantic_indices;
+ src_len = source->shader->out.count;
+ }
+ else {
+ src_semantics = kernel->in.semantic_names;
+ src_indices = kernel->in.semantic_indices;
+ src_len = kernel->in.count;
+ }
+
+ /* no change */
+ if (kernel->routing_initialized &&
+ routing->source_skip + routing->source_len <= src_len &&
+ kernel->routing_sprite_coord_enable == sprite_coord_enable &&
+ !memcmp(kernel->routing_src_semantics,
+ &src_semantics[routing->source_skip],
+ sizeof(kernel->routing_src_semantics[0]) * routing->source_len) &&
+ !memcmp(kernel->routing_src_indices,
+ &src_indices[routing->source_skip],
+ sizeof(kernel->routing_src_indices[0]) * routing->source_len))
+ return false;
+
+ if (source) {
+ /* skip PSIZE and POSITION (how about the optional CLIPDISTs?) */
+ assert(src_semantics[0] == TGSI_SEMANTIC_PSIZE);
+ assert(src_semantics[1] == TGSI_SEMANTIC_POSITION);
+ routing->source_skip = 2;
+
+ routing->source_len = src_len - routing->source_skip;
+ src_semantics += routing->source_skip;
+ src_indices += routing->source_skip;
+ }
+ else {
+ routing->source_skip = 0;
+ routing->source_len = src_len;
+ }
+
+ routing->const_interp_enable = kernel->in.const_interp_enable;
+ routing->point_sprite_enable = 0;
+ routing->swizzle_enable = false;
+
+ assert(kernel->in.count <= Elements(routing->swizzles));
+ dst_len = MIN2(kernel->in.count, Elements(routing->swizzles));
+ max_src_slot = -1;
+
+ for (dst_slot = 0; dst_slot < dst_len; dst_slot++) {
+ const int semantic = kernel->in.semantic_names[dst_slot];
+ const int index = kernel->in.semantic_indices[dst_slot];
+ int src_slot;
+
+ if (semantic == TGSI_SEMANTIC_GENERIC &&
+ (sprite_coord_enable & (1 << index)))
+ routing->point_sprite_enable |= 1 << dst_slot;
+
+ if (source) {
+ src_slot = route_attr(src_semantics, src_indices,
+ routing->source_len, semantic, index);
+
+ /*
+ * The source shader stage does not output this attribute. The value
+ * is supposed to be undefined, unless the attribute goes through
+ * point sprite replacement or the attribute is
+ * TGSI_SEMANTIC_POSITION. In all cases, we do not care which source
+ * attribute is picked.
+ *
+ * We should update the kernel code and omit the output of
+ * TGSI_SEMANTIC_POSITION here.
+ */
+ if (src_slot < 0)
+ src_slot = 0;
+ }
+ else {
+ src_slot = dst_slot;
+ }
+
+ routing->swizzles[dst_slot] = src_slot;
+
+ /* use the following slot for two-sided lighting */
+ if (semantic == TGSI_SEMANTIC_COLOR && light_twoside &&
+ src_slot + 1 < routing->source_len &&
+ src_semantics[src_slot + 1] == TGSI_SEMANTIC_BCOLOR &&
+ src_indices[src_slot + 1] == index) {
+ routing->swizzles[dst_slot] |= ATTRIBUTE_SWIZZLE_INPUTATTR_FACING <<
+ ATTRIBUTE_SWIZZLE_SHIFT;
+ src_slot++;
+ }
+
+ if (routing->swizzles[dst_slot] != dst_slot)
+ routing->swizzle_enable = true;
+
+ if (max_src_slot < src_slot)
+ max_src_slot = src_slot;
+ }
+
+ memset(&routing->swizzles[dst_slot], 0, sizeof(routing->swizzles) -
+ sizeof(routing->swizzles[0]) * dst_slot);
+
+ /*
+ * From the Sandy Bridge PRM, volume 2 part 1, page 248:
+ *
+ * "It is UNDEFINED to set this field (Vertex URB Entry Read Length) to
+ * 0 indicating no Vertex URB data to be read.
+ *
+ * This field should be set to the minimum length required to read the
+ * maximum source attribute. The maximum source attribute is indicated
+ * by the maximum value of the enabled Attribute # Source Attribute if
+ * Attribute Swizzle Enable is set, Number of Output Attributes-1 if
+ * enable is not set.
+ *
+ * read_length = ceiling((max_source_attr+1)/2)
+ *
+ * [errata] Corruption/Hang possible if length programmed larger than
+ * recommended"
+ */
+ routing->source_len = max_src_slot + 1;
+
+ /* remember the states of the source */
+ kernel->routing_initialized = true;
+ kernel->routing_sprite_coord_enable = sprite_coord_enable;
+ memcpy(kernel->routing_src_semantics, src_semantics,
+ sizeof(kernel->routing_src_semantics[0]) * routing->source_len);
+ memcpy(kernel->routing_src_indices, src_indices,
+ sizeof(kernel->routing_src_indices[0]) * routing->source_len);
+
+ return true;
+}
+
/**
* Return the cache offset of the selected kernel. This must be called after
* ilo_shader_select_kernel() and ilo_shader_cache_upload().
case ILO_KERNEL_URB_DATA_START_REG:
val = kernel->in.start_grf;
break;
+ case ILO_KERNEL_SKIP_CBUF0_UPLOAD:
+ val = kernel->skip_cbuf0_upload;
+ break;
+ case ILO_KERNEL_PCB_CBUF0_SIZE:
+ val = kernel->pcb.cbuf0_size;
+ break;
case ILO_KERNEL_VS_INPUT_INSTANCEID:
val = shader->info.has_instanceid;
return &kernel->cso;
}
+
+/**
+ * Return the SO info of the selected kernel.
+ */
+const struct pipe_stream_output_info *
+ilo_shader_get_kernel_so_info(const struct ilo_shader_state *shader)
+{
+ const struct ilo_shader *kernel = shader->shader;
+
+ assert(kernel);
+
+ return &kernel->so_info;
+}
+
+/**
+ * Return the routing info of the selected kernel.
+ */
+const struct ilo_kernel_routing *
+ilo_shader_get_kernel_routing(const struct ilo_shader_state *shader)
+{
+ const struct ilo_shader *kernel = shader->shader;
+
+ assert(kernel);
+
+ return &kernel->routing;
+}