#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_pointer.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
#include "util/u_dump.h"
#include "util/u_string.h"
#include "util/simple_list.h"
#include "gallivm/lp_bld_intr.h"
#include "gallivm/lp_bld_logic.h"
#include "gallivm/lp_bld_tgsi.h"
+#include "gallivm/lp_bld_nir.h"
#include "gallivm/lp_bld_swizzle.h"
#include "gallivm/lp_bld_flow.h"
#include "gallivm/lp_bld_debug.h"
#include "lp_flush.h"
#include "lp_state_fs.h"
#include "lp_rast.h"
-
+#include "nir/nir_to_tgsi_info.h"
/** Fragment shader number (for debugging) */
static unsigned fs_no = 0;
LLVMValueRef num_loop,
struct lp_build_interp_soa_context *interp,
const struct lp_build_sampler_soa *sampler,
+ const struct lp_build_image_soa *image,
LLVMValueRef mask_store,
LLVMValueRef (*out_color)[4],
LLVMValueRef depth_ptr,
memset(&system_values, 0, sizeof(system_values));
+ /* truncate then sign extend. */
+ system_values.front_facing = LLVMBuildTrunc(gallivm->builder, facing, LLVMInt1TypeInContext(gallivm->context), "");
+ system_values.front_facing = LLVMBuildSExt(gallivm->builder, system_values.front_facing, LLVMInt32TypeInContext(gallivm->context), "");
+
if (key->depth.enabled ||
key->stencil[0].enabled) {
params.info = &shader->info.base;
params.ssbo_ptr = ssbo_ptr;
params.ssbo_sizes_ptr = num_ssbo_ptr;
+ params.image = image;
/* Build the actual shader */
- lp_build_tgsi_soa(gallivm, tokens, ¶ms,
- outputs);
+ if (shader->base.type == PIPE_SHADER_IR_TGSI)
+ lp_build_tgsi_soa(gallivm, tokens, ¶ms,
+ outputs);
+ else
+ lp_build_nir_soa(gallivm, shader->base.ir.nir, ¶ms,
+ outputs);
/* Alpha test */
if (key->alpha.enabled) {
for (j = 0; j < src_fmt->nr_channels; ++j) {
unsigned mask = 0;
unsigned sa = src_fmt->channel[j].shift;
-#ifdef PIPE_ARCH_LITTLE_ENDIAN
+#if UTIL_ARCH_LITTLE_ENDIAN
unsigned from_lsb = j;
#else
unsigned from_lsb = src_fmt->nr_channels - j - 1;
for (j = 0; j < src_fmt->nr_channels; ++j) {
unsigned mask = 0;
unsigned sa = src_fmt->channel[j].shift;
-#ifdef PIPE_ARCH_LITTLE_ENDIAN
+ unsigned sz_a = src_fmt->channel[j].size;
+#if UTIL_ARCH_LITTLE_ENDIAN
unsigned from_lsb = j;
#else
unsigned from_lsb = src_fmt->nr_channels - j - 1;
if (src_type.norm) {
chans[j] = scale_bits(gallivm, blend_type.width,
src_fmt->channel[j].size, chans[j], src_type);
+ } else if (!src_type.floating && sz_a < blend_type.width) {
+ LLVMValueRef mask_val = lp_build_const_int_vec(gallivm, src_type, (1UL << sz_a) - 1);
+ LLVMValueRef mask = LLVMBuildICmp(builder, LLVMIntUGT, chans[j], mask_val, "");
+ chans[j] = LLVMBuildSelect(builder, mask, mask_val, chans[j], "");
}
/* Insert bits */
struct lp_type blend_type;
LLVMTypeRef fs_elem_type;
LLVMTypeRef blend_vec_type;
- LLVMTypeRef arg_types[13];
+ LLVMTypeRef arg_types[15];
LLVMTypeRef func_type;
LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context);
LLVMTypeRef int8_type = LLVMInt8TypeInContext(gallivm->context);
LLVMValueRef dady_ptr;
LLVMValueRef color_ptr_ptr;
LLVMValueRef stride_ptr;
+ LLVMValueRef color_sample_stride_ptr;
LLVMValueRef depth_ptr;
LLVMValueRef depth_stride;
+ LLVMValueRef depth_sample_stride;
LLVMValueRef mask_input;
LLVMValueRef thread_data_ptr;
LLVMBasicBlockRef block;
LLVMBuilderRef builder;
struct lp_build_sampler_soa *sampler;
+ struct lp_build_image_soa *image;
struct lp_build_interp_soa_context interp;
LLVMValueRef fs_mask[16 / 4];
LLVMValueRef fs_out_color[PIPE_MAX_COLOR_BUFS][TGSI_NUM_CHANNELS][16 / 4];
arg_types[10] = variant->jit_thread_data_ptr_type; /* per thread data */
arg_types[11] = LLVMPointerType(int32_type, 0); /* stride */
arg_types[12] = int32_type; /* depth_stride */
+ arg_types[13] = LLVMPointerType(int32_type, 0); /* color sample strides */
+ arg_types[14] = int32_type; /* depth sample stride */
func_type = LLVMFunctionType(LLVMVoidTypeInContext(gallivm->context),
arg_types, ARRAY_SIZE(arg_types), 0);
thread_data_ptr = LLVMGetParam(function, 10);
stride_ptr = LLVMGetParam(function, 11);
depth_stride = LLVMGetParam(function, 12);
+ color_sample_stride_ptr = LLVMGetParam(function, 13);
+ depth_sample_stride = LLVMGetParam(function, 14);
lp_build_name(context_ptr, "context");
lp_build_name(x, "x");
lp_build_name(thread_data_ptr, "thread_data");
lp_build_name(stride_ptr, "stride_ptr");
lp_build_name(depth_stride, "depth_stride");
+ lp_build_name(color_sample_stride_ptr, "color_sample_stride_ptr");
+ lp_build_name(depth_sample_stride, "depth_sample_stride");
/*
* Function body
/* code generated texture sampling */
sampler = lp_llvm_sampler_soa_create(key->samplers);
+ image = lp_llvm_image_soa_create(lp_fs_variant_key_images(key));
num_fs = 16 / fs_type.length; /* number of loops per 4x4 stamp */
/* for 1d resources only run "upper half" of stamp */
num_loop,
&interp,
sampler,
+ image,
mask_store, /* output */
color_store,
depth_ptr,
}
sampler->destroy(sampler);
-
+ image->destroy(image);
/* Loop over color outputs / color buffers to do blending.
*/
for(cbuf = 0; cbuf < key->nr_cbufs; cbuf++) {
texture->pot_height,
texture->pot_depth);
}
+ struct lp_image_static_state *images = lp_fs_variant_key_images(key);
+ for (i = 0; i < key->nr_images; ++i) {
+ const struct lp_static_texture_state *image = &images[i].image_state;
+ debug_printf("image[%u] = \n", i);
+ debug_printf(" .format = %s\n",
+ util_format_name(image->format));
+ debug_printf(" .target = %s\n",
+ util_str_tex_target(image->target, TRUE));
+ debug_printf(" .level_zero_only = %u\n",
+ image->level_zero_only);
+ debug_printf(" .pot = %u %u %u\n",
+ image->pot_width,
+ image->pot_height,
+ image->pot_depth);
+ }
}
void
lp_debug_fs_variant(struct lp_fragment_shader_variant *variant)
{
- debug_printf("llvmpipe: Fragment shader #%u variant #%u:\n",
+ debug_printf("llvmpipe: Fragment shader #%u variant #%u:\n",
variant->shader->no, variant->no);
- tgsi_dump(variant->shader->base.tokens, 0);
+ if (variant->shader->base.type == PIPE_SHADER_IR_TGSI)
+ tgsi_dump(variant->shader->base.tokens, 0);
+ else
+ nir_print_shader(variant->shader->base.ir.nir, stderr);
dump_fs_variant_key(&variant->key);
debug_printf("variant->opaque = %u\n", variant->opaque);
debug_printf("\n");
struct lp_fragment_shader *shader;
int nr_samplers;
int nr_sampler_views;
+ int nr_images;
int i;
shader = CALLOC_STRUCT(lp_fragment_shader);
shader->no = fs_no++;
make_empty_list(&shader->variants);
- /* get/save the summary info for this shader */
- lp_build_tgsi_info(templ->tokens, &shader->info);
+ shader->base.type = templ->type;
+ if (templ->type == PIPE_SHADER_IR_TGSI) {
+ /* get/save the summary info for this shader */
+ lp_build_tgsi_info(templ->tokens, &shader->info);
- /* we need to keep a local copy of the tokens */
- shader->base.tokens = tgsi_dup_tokens(templ->tokens);
+ /* we need to keep a local copy of the tokens */
+ shader->base.tokens = tgsi_dup_tokens(templ->tokens);
+ } else {
+ shader->base.ir.nir = templ->ir.nir;
+ nir_tgsi_scan_shader(templ->ir.nir, &shader->info.base, true);
+ }
shader->draw_data = draw_create_fragment_shader(llvmpipe->draw, templ);
if (shader->draw_data == NULL) {
nr_samplers = shader->info.base.file_max[TGSI_FILE_SAMPLER] + 1;
nr_sampler_views = shader->info.base.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
-
- shader->variant_key_size = lp_fs_variant_key_size(MAX2(nr_samplers, nr_sampler_views));
+ nr_images = shader->info.base.file_max[TGSI_FILE_IMAGE] + 1;
+ shader->variant_key_size = lp_fs_variant_key_size(MAX2(nr_samplers, nr_sampler_views), nr_images);
for (i = 0; i < shader->info.base.num_inputs; i++) {
shader->inputs[i].usage_mask = shader->info.base.input_usage_mask[i];
llvmpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
-
- if (llvmpipe->fs == fs)
+ struct lp_fragment_shader *lp_fs = (struct lp_fragment_shader *)fs;
+ if (llvmpipe->fs == lp_fs)
return;
- llvmpipe->fs = (struct lp_fragment_shader *) fs;
-
draw_bind_fragment_shader(llvmpipe->draw,
- (llvmpipe->fs ? llvmpipe->fs->draw_data : NULL));
+ (lp_fs ? lp_fs->draw_data : NULL));
+
+ llvmpipe->fs = lp_fs;
llvmpipe->dirty |= LP_NEW_FS;
}
/* Delete draw module's data */
draw_delete_fragment_shader(llvmpipe->draw, shader->draw_data);
+ if (shader->base.ir.nir)
+ ralloc_free(shader->base.ir.nir);
assert(shader->variants_cached == 0);
FREE((void *) shader->base.tokens);
FREE(shader);
}
if (shader == PIPE_SHADER_VERTEX ||
- shader == PIPE_SHADER_GEOMETRY) {
+ shader == PIPE_SHADER_GEOMETRY ||
+ shader == PIPE_SHADER_TESS_CTRL ||
+ shader == PIPE_SHADER_TESS_EVAL) {
/* Pass the constants to the 'draw' module */
const unsigned size = cb ? cb->buffer_size : 0;
const ubyte *data;
draw_set_mapped_constant_buffer(llvmpipe->draw, shader,
index, data, size);
}
- else {
+ else if (shader == PIPE_SHADER_COMPUTE)
+ llvmpipe->cs_dirty |= LP_CSNEW_CONSTANTS;
+ else
llvmpipe->dirty |= LP_NEW_FS_CONSTANTS;
- }
if (cb && cb->user_buffer) {
pipe_resource_reference(&constants, NULL);
util_copy_shader_buffer(&llvmpipe->ssbos[shader][i], buffer);
if (shader == PIPE_SHADER_VERTEX ||
- shader == PIPE_SHADER_GEOMETRY) {
+ shader == PIPE_SHADER_GEOMETRY ||
+ shader == PIPE_SHADER_TESS_CTRL ||
+ shader == PIPE_SHADER_TESS_EVAL) {
const unsigned size = buffer ? buffer->buffer_size : 0;
const ubyte *data = NULL;
if (buffer && buffer->buffer)
data += buffer->buffer_offset;
draw_set_mapped_shader_buffer(llvmpipe->draw, shader,
i, data, size);
+ } else if (shader == PIPE_SHADER_COMPUTE) {
+ llvmpipe->cs_dirty |= LP_CSNEW_SSBOS;
} else if (shader == PIPE_SHADER_FRAGMENT) {
llvmpipe->dirty |= LP_NEW_FS_SSBOS;
}
}
}
+static void
+llvmpipe_set_shader_images(struct pipe_context *pipe,
+ enum pipe_shader_type shader, unsigned start_slot,
+ unsigned count, const struct pipe_image_view *images)
+{
+ struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
+ unsigned i, idx;
+
+ draw_flush(llvmpipe->draw);
+ for (i = start_slot, idx = 0; i < start_slot + count; i++, idx++) {
+ const struct pipe_image_view *image = images ? &images[idx] : NULL;
+
+ util_copy_image_view(&llvmpipe->images[shader][i], image);
+ }
+
+ llvmpipe->num_images[shader] = start_slot + count;
+ if (shader == PIPE_SHADER_VERTEX ||
+ shader == PIPE_SHADER_GEOMETRY ||
+ shader == PIPE_SHADER_TESS_CTRL ||
+ shader == PIPE_SHADER_TESS_EVAL) {
+ draw_set_images(llvmpipe->draw,
+ shader,
+ llvmpipe->images[shader],
+ start_slot + count);
+ } else if (shader == PIPE_SHADER_COMPUTE)
+ llvmpipe->cs_dirty |= LP_CSNEW_IMAGES;
+ else
+ llvmpipe->dirty |= LP_NEW_FS_IMAGES;
+}
+
/**
* Return the blend factor equivalent to a destination alpha of one.
*/
/* alpha.ref_value is passed in jit_context */
key->flatshade = lp->rasterizer->flatshade;
- if (lp->active_occlusion_queries) {
+ if (lp->active_occlusion_queries && !lp->queries_disabled) {
key->occlusion_count = TRUE;
}
}
}
}
+
+ struct lp_image_static_state *lp_image;
+ lp_image = lp_fs_variant_key_images(key);
+ key->nr_images = shader->info.base.file_max[TGSI_FILE_IMAGE] + 1;
+ for (i = 0; i < key->nr_images; ++i) {
+ if (shader->info.base.file_mask[TGSI_FILE_IMAGE] & (1 << i)) {
+ lp_sampler_static_texture_state_image(&lp_image[i].image_state,
+ &lp->images[PIPE_SHADER_FRAGMENT][i]);
+ }
+ }
return key;
}
llvmpipe->pipe.set_constant_buffer = llvmpipe_set_constant_buffer;
llvmpipe->pipe.set_shader_buffers = llvmpipe_set_shader_buffers;
+ llvmpipe->pipe.set_shader_images = llvmpipe_set_shader_images;
}