[VK_SHADER_STAGE_COMPUTE] = MESA_SHADER_COMPUTE,
};
-static bool
-is_scalar_shader_stage(const struct brw_compiler *compiler, VkShaderStage stage)
+bool
+anv_is_scalar_shader_stage(const struct brw_compiler *compiler,
+ VkShaderStage stage)
{
- switch (stage) {
- case VK_SHADER_STAGE_VERTEX:
- return compiler->scalar_vs;
- case VK_SHADER_STAGE_GEOMETRY:
- return false;
- case VK_SHADER_STAGE_FRAGMENT:
- case VK_SHADER_STAGE_COMPUTE:
- return true;
- default:
- unreachable("Unsupported shader stage");
- }
+ return compiler->scalar_stage[vk_shader_stage_to_mesa_stage[stage]];
}
/* Eventually, this will become part of anv_CreateShader. Unfortunately,
}
nir_validate_shader(nir);
+ /* Vulkan uses the separate-shader linking model */
+ nir->info.separate_shader = true;
+
/* Make sure the provided shader has exactly one entrypoint and that the
* name matches the name that came in from the VkShader.
*/
}
assert(entrypoint != NULL);
- brw_preprocess_nir(nir, &device->info,
- is_scalar_shader_stage(compiler, vk_stage));
+ nir = brw_preprocess_nir(nir, compiler->scalar_stage[stage]);
nir_shader_gather_info(nir, entrypoint);
anv_reloc_list_finish(&pipeline->batch_relocs, pipeline->device);
anv_state_stream_finish(&pipeline->program_stream);
- anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
+ if (pipeline->blend_state.map)
+ anv_state_pool_free(&device->dynamic_state_pool, pipeline->blend_state);
anv_device_free(pipeline->device, pipeline);
}
[VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_ADJ] = _3DPRIM_LINESTRIP_ADJ,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_ADJ] = _3DPRIM_TRILIST_ADJ,
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_ADJ] = _3DPRIM_TRISTRIP_ADJ,
- [VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1
+/* [VK_PRIMITIVE_TOPOLOGY_PATCH] = _3DPRIM_PATCHLIST_1 */
};
static void
/* XXX: Handle sampler_prog_key */
}
+static void
+populate_gs_prog_key(const struct brw_device_info *devinfo,
+ struct brw_gs_prog_key *key)
+{
+ memset(key, 0, sizeof(*key));
+
+ populate_sampler_prog_key(devinfo, &key->tex);
+}
+
static void
populate_wm_prog_key(const struct brw_device_info *devinfo,
const VkGraphicsPipelineCreateInfo *info,
populate_sampler_prog_key(devinfo, &key->tex);
+ /* TODO: Fill out key->input_slots_valid */
+
/* Vulkan doesn't specify a default */
key->high_quality_derivatives = false;
if (nir == NULL)
return NULL;
- bool have_push_constants = false;
- nir_foreach_variable(var, &nir->uniforms) {
- if (!glsl_type_is_sampler(var->type)) {
- have_push_constants = true;
- break;
- }
- }
+ anv_nir_lower_push_constants(nir, anv_is_scalar_shader_stage(compiler, stage));
/* Figure out the number of parameters */
prog_data->nr_params = 0;
- if (have_push_constants) {
+ if (nir->num_uniforms > 0) {
/* If the shader uses any push constants at all, we'll just give
* them the maximum possible number
*/
}
if (pipeline->layout && pipeline->layout->stage[stage].has_dynamic_offsets)
- prog_data->nr_params += MAX_DYNAMIC_BUFFERS;
+ prog_data->nr_params += MAX_DYNAMIC_BUFFERS * 2;
if (prog_data->nr_params > 0) {
prog_data->param = (const gl_constant_value **)
* params array, it doesn't really matter what we put here.
*/
struct anv_push_constants *null_data = NULL;
- if (have_push_constants) {
+ if (nir->num_uniforms > 0) {
/* Fill out the push constants section of the param array */
for (unsigned i = 0; i < MAX_PUSH_CONSTANTS_SIZE / sizeof(float); i++)
prog_data->param[i] = (const gl_constant_value *)
prog_data->binding_table.size_bytes = 0;
prog_data->binding_table.texture_start = bias;
prog_data->binding_table.ubo_start = bias;
+ prog_data->binding_table.ssbo_start = bias;
prog_data->binding_table.image_start = bias;
/* Finish the optimization and compilation process */
- brw_postprocess_nir(nir, &pipeline->device->info,
- is_scalar_shader_stage(compiler, stage));
+ nir = brw_lower_nir(nir, &pipeline->device->info, NULL,
+ anv_is_scalar_shader_stage(compiler, stage));
/* nir_lower_io will only handle the push constants; we need to set this
* to the full number of possible uniforms.
brw_compute_vue_map(&pipeline->device->info,
&prog_data->base.vue_map,
nir->info.outputs_written,
- false /* XXX: Do SSO? */);
+ nir->info.separate_shader);
unsigned code_size;
const unsigned *shader_code =
return VK_SUCCESS;
}
+static VkResult
+anv_pipeline_compile_gs(struct anv_pipeline *pipeline,
+ const VkGraphicsPipelineCreateInfo *info,
+ struct anv_shader *shader)
+{
+ const struct brw_compiler *compiler =
+ pipeline->device->instance->physicalDevice.compiler;
+ struct brw_gs_prog_data *prog_data = &pipeline->gs_prog_data;
+ struct brw_gs_prog_key key;
+
+ populate_gs_prog_key(&pipeline->device->info, &key);
+
+ /* TODO: Look up shader in cache */
+
+ memset(prog_data, 0, sizeof(*prog_data));
+
+ nir_shader *nir = anv_pipeline_compile(pipeline, shader,
+ VK_SHADER_STAGE_GEOMETRY,
+ &prog_data->base.base);
+ if (nir == NULL)
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+
+ void *mem_ctx = ralloc_context(NULL);
+
+ if (shader->module->nir == NULL)
+ ralloc_steal(mem_ctx, nir);
+
+ brw_compute_vue_map(&pipeline->device->info,
+ &prog_data->base.vue_map,
+ nir->info.outputs_written,
+ nir->info.separate_shader);
+
+ unsigned code_size;
+ const unsigned *shader_code =
+ brw_compile_gs(compiler, NULL, mem_ctx, &key, prog_data, nir,
+ NULL, -1, &code_size, NULL);
+ if (shader_code == NULL) {
+ ralloc_free(mem_ctx);
+ return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+ }
+
+ /* TODO: SIMD8 GS */
+ pipeline->gs_vec4 =
+ anv_pipeline_upload_kernel(pipeline, shader_code, code_size);
+ pipeline->gs_vertex_count = nir->info.gs.vertices_in;
+
+ ralloc_free(mem_ctx);
+
+ anv_pipeline_add_compiled_stage(pipeline, VK_SHADER_STAGE_GEOMETRY,
+ &prog_data->base.base);
+
+ return VK_SUCCESS;
+}
+
static VkResult
anv_pipeline_compile_fs(struct anv_pipeline *pipeline,
const VkGraphicsPipelineCreateInfo *info,
case VK_SHADER_STAGE_VERTEX:
anv_pipeline_compile_vs(pipeline, pCreateInfo, shader);
break;
+ case VK_SHADER_STAGE_GEOMETRY:
+ anv_pipeline_compile_gs(pipeline, pCreateInfo, shader);
+ break;
case VK_SHADER_STAGE_FRAGMENT:
anv_pipeline_compile_fs(pipeline, pCreateInfo, shader);
break;
switch (device->info.gen) {
case 7:
- return gen7_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
+ if (device->info.is_haswell)
+ return gen75_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
+ else
+ return gen7_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
case 8:
return gen8_graphics_pipeline_create(_device, pCreateInfo, extra, pPipeline);
default:
switch (device->info.gen) {
case 7:
- return gen7_compute_pipeline_create(_device, pCreateInfo, pPipeline);
+ if (device->info.is_haswell)
+ return gen75_compute_pipeline_create(_device, pCreateInfo, pPipeline);
+ else
+ return gen7_compute_pipeline_create(_device, pCreateInfo, pPipeline);
case 8:
return gen8_compute_pipeline_create(_device, pCreateInfo, pPipeline);
default:
return VK_SUCCESS;
}
-
-// Pipeline layout functions
-
-VkResult anv_CreatePipelineLayout(
- VkDevice _device,
- const VkPipelineLayoutCreateInfo* pCreateInfo,
- VkPipelineLayout* pPipelineLayout)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- struct anv_pipeline_layout l, *layout;
-
- assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
-
- l.num_sets = pCreateInfo->descriptorSetCount;
-
- unsigned dynamic_offset_count = 0;
-
- memset(l.stage, 0, sizeof(l.stage));
- for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
- ANV_FROM_HANDLE(anv_descriptor_set_layout, set_layout,
- pCreateInfo->pSetLayouts[set]);
- l.set[set].layout = set_layout;
-
- l.set[set].dynamic_offset_start = dynamic_offset_count;
- for (uint32_t b = 0; b < set_layout->binding_count; b++) {
- if (set_layout->binding[b].dynamic_offset_index >= 0)
- dynamic_offset_count += set_layout->binding[b].array_size;
- }
-
- for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
- l.set[set].stage[s].surface_start = l.stage[s].surface_count;
- l.set[set].stage[s].sampler_start = l.stage[s].sampler_count;
-
- for (uint32_t b = 0; b < set_layout->binding_count; b++) {
- unsigned array_size = set_layout->binding[b].array_size;
-
- if (set_layout->binding[b].stage[s].surface_index >= 0) {
- l.stage[s].surface_count += array_size;
-
- if (set_layout->binding[b].dynamic_offset_index >= 0)
- l.stage[s].has_dynamic_offsets = true;
- }
-
- if (set_layout->binding[b].stage[s].sampler_index >= 0)
- l.stage[s].sampler_count += array_size;
- }
- }
- }
-
- unsigned num_bindings = 0;
- for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++)
- num_bindings += l.stage[s].surface_count + l.stage[s].sampler_count;
-
- size_t size = sizeof(*layout) + num_bindings * sizeof(layout->entries[0]);
-
- layout = anv_device_alloc(device, size, 8, VK_SYSTEM_ALLOC_TYPE_API_OBJECT);
- if (layout == NULL)
- return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
-
- /* Now we can actually build our surface and sampler maps */
- struct anv_pipeline_binding *entry = layout->entries;
- for (VkShaderStage s = 0; s < VK_SHADER_STAGE_NUM; s++) {
- l.stage[s].surface_to_descriptor = entry;
- entry += l.stage[s].surface_count;
- l.stage[s].sampler_to_descriptor = entry;
- entry += l.stage[s].sampler_count;
-
- int surface = 0;
- int sampler = 0;
- for (uint32_t set = 0; set < pCreateInfo->descriptorSetCount; set++) {
- struct anv_descriptor_set_layout *set_layout = l.set[set].layout;
-
- unsigned set_offset = 0;
- for (uint32_t b = 0; b < set_layout->binding_count; b++) {
- unsigned array_size = set_layout->binding[b].array_size;
-
- if (set_layout->binding[b].stage[s].surface_index >= 0) {
- assert(surface == l.set[set].stage[s].surface_start +
- set_layout->binding[b].stage[s].surface_index);
- for (unsigned i = 0; i < array_size; i++) {
- l.stage[s].surface_to_descriptor[surface + i].set = set;
- l.stage[s].surface_to_descriptor[surface + i].offset = set_offset + i;
- }
- surface += array_size;
- }
-
- if (set_layout->binding[b].stage[s].sampler_index >= 0) {
- assert(sampler == l.set[set].stage[s].sampler_start +
- set_layout->binding[b].stage[s].sampler_index);
- for (unsigned i = 0; i < array_size; i++) {
- l.stage[s].sampler_to_descriptor[sampler + i].set = set;
- l.stage[s].sampler_to_descriptor[sampler + i].offset = set_offset + i;
- }
- sampler += array_size;
- }
-
- set_offset += array_size;
- }
- }
- }
-
- /* Finally, we're done setting it up, copy into the allocated version */
- *layout = l;
-
- *pPipelineLayout = anv_pipeline_layout_to_handle(layout);
-
- return VK_SUCCESS;
-}
-
-void anv_DestroyPipelineLayout(
- VkDevice _device,
- VkPipelineLayout _pipelineLayout)
-{
- ANV_FROM_HANDLE(anv_device, device, _device);
- ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _pipelineLayout);
-
- anv_device_free(device, pipeline_layout);
-}