llvmpipe: implement GL_ARB_sample_locations
Needing the positions both in the scene for rasterization (in fixed point) and in the fs (as floats) is a bit awkward, for now just put it in fs key. Otherwise pretty straight forward. Reviewed-by: Michal Krol <michal.krol@broadcom.com> Reviewed-by: Brian Paul <brian.paul@broadcom.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37181>
This commit is contained in:
committed by
Marge Bot
parent
60924b4819
commit
b0be900f93
+1
-1
@@ -305,7 +305,7 @@ Khronos, ARB, and OES extensions that are not part of any OpenGL or OpenGL ES ve
|
||||
GL_ARB_parallel_shader_compile DONE (freedreno, llvmpipe, radeonsi, etnaviv, virgl, zink, iris, crocus/gen6+, asahi)
|
||||
GL_ARB_post_depth_coverage DONE (freedreno/a6xx, nvc0, radeonsi, llvmpipe, zink, iris/gen9+)
|
||||
GL_ARB_robustness_isolation not started
|
||||
GL_ARB_sample_locations DONE (freedreno/a6xx, nvc0, zink)
|
||||
GL_ARB_sample_locations DONE (freedreno/a6xx, nvc0, zink, llvmpipe)
|
||||
GL_ARB_seamless_cubemap_per_texture DONE (etnaviv/SEAMLESS_CUBE_MAP, freedreno, nvc0, r600, radeonsi, softpipe, llvmpipe, virgl, zink, asahi, iris, crocus)
|
||||
GL_ARB_shader_ballot DONE (llvmpipe, nvc0, radeonsi, zink, iris, crocus/gen8, d3d12, asahi)
|
||||
GL_ARB_shader_clock DONE (freedreno/a6xx, nv50, nvc0, r600, radeonsi, llvmpipe, virgl, panfrost/v6+, zink, iris, crocus/gen7+)
|
||||
|
||||
@@ -83,6 +83,8 @@ struct llvmpipe_context {
|
||||
/** Other rendering state */
|
||||
unsigned sample_mask;
|
||||
unsigned min_samples;
|
||||
uint8_t sample_locations[LP_MAX_SAMPLES];
|
||||
bool sample_locations_enabled;
|
||||
struct pipe_blend_color blend_color;
|
||||
struct pipe_stencil_ref stencil_ref;
|
||||
struct pipe_clip_state clip;
|
||||
|
||||
@@ -639,18 +639,6 @@ lp_scene_begin_binning(struct lp_scene *scene,
|
||||
}
|
||||
|
||||
scene->fb_max_layer = max_layer;
|
||||
scene->fb_max_samples = util_framebuffer_get_num_samples(fb);
|
||||
if (scene->fb_max_samples == 4) {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
scene->fixed_sample_pos[i][0] = util_iround(lp_sample_pos_4x[i][0] * FIXED_ONE);
|
||||
scene->fixed_sample_pos[i][1] = util_iround(lp_sample_pos_4x[i][1] * FIXED_ONE);
|
||||
}
|
||||
} else if (scene->fb_max_samples == 8) {
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
scene->fixed_sample_pos[i][0] = util_iround(lp_sample_pos_8x[i][0] * FIXED_ONE);
|
||||
scene->fixed_sample_pos[i][1] = util_iround(lp_sample_pos_8x[i][1] * FIXED_ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -360,6 +360,7 @@ llvmpipe_init_screen_caps(struct pipe_screen *screen)
|
||||
caps->memobj = true;
|
||||
#endif
|
||||
caps->sampler_reduction_minmax = true;
|
||||
caps->programmable_sample_locations = true;
|
||||
caps->texture_query_samples = true;
|
||||
caps->shader_group_vote = true;
|
||||
caps->shader_ballot = true;
|
||||
@@ -391,6 +392,26 @@ llvmpipe_init_screen_caps(struct pipe_screen *screen)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
llvmpipe_get_sample_pixel_grid(struct pipe_screen *pscreen,
|
||||
unsigned sample_count,
|
||||
unsigned *width, unsigned *height)
|
||||
{
|
||||
switch (sample_count) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
*width = 1;
|
||||
*height = 1;
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE("illegal sample count");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
llvmpipe_get_driver_uuid(struct pipe_screen *pscreen, char *uuid)
|
||||
{
|
||||
@@ -967,6 +988,7 @@ llvmpipe_create_screen(struct sw_winsys *winsys)
|
||||
screen->base.get_device_vendor = llvmpipe_get_vendor; // TODO should be the CPU vendor
|
||||
screen->base.get_screen_fd = llvmpipe_screen_get_fd;
|
||||
screen->base.is_format_supported = llvmpipe_is_format_supported;
|
||||
screen->base.get_sample_pixel_grid = llvmpipe_get_sample_pixel_grid;
|
||||
|
||||
screen->base.context_create = llvmpipe_create_context;
|
||||
screen->base.flush_frontbuffer = llvmpipe_flush_frontbuffer;
|
||||
|
||||
@@ -113,6 +113,35 @@ lp_setup_get_empty_scene(struct lp_setup_context *setup)
|
||||
|
||||
setup->scene = setup->scenes[i];
|
||||
setup->scene->permit_linear_rasterizer = setup->permit_linear_rasterizer;
|
||||
|
||||
/* XXX: doing that here is ugly... */
|
||||
setup->scene->fb_max_samples = util_framebuffer_get_num_samples(&setup->fb);
|
||||
if (setup->scene->fb_max_samples == 4) {
|
||||
if (setup->sample_locations_enabled) {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
setup->scene->fixed_sample_pos[i][0] = (setup->sample_locations[i] & 0xF) << (FIXED_ORDER - 4);
|
||||
setup->scene->fixed_sample_pos[i][1] = (setup->sample_locations[i] >> 4) << (FIXED_ORDER - 4);
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
setup->scene->fixed_sample_pos[i][0] = util_iround(lp_sample_pos_4x[i][0] * FIXED_ONE);
|
||||
setup->scene->fixed_sample_pos[i][1] = util_iround(lp_sample_pos_4x[i][1] * FIXED_ONE);
|
||||
}
|
||||
}
|
||||
} else if (setup->scene->fb_max_samples == 8) {
|
||||
if (setup->sample_locations_enabled) {
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
setup->scene->fixed_sample_pos[i][0] = (setup->sample_locations[i] & 0xF) << (FIXED_ORDER - 4);
|
||||
setup->scene->fixed_sample_pos[i][1] = (setup->sample_locations[i] >> 4) << (FIXED_ORDER - 4);
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
setup->scene->fixed_sample_pos[i][0] = util_iround(lp_sample_pos_8x[i][0] * FIXED_ONE);
|
||||
setup->scene->fixed_sample_pos[i][1] = util_iround(lp_sample_pos_8x[i][1] * FIXED_ONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lp_scene_begin_binning(setup->scene, &setup->fb);
|
||||
}
|
||||
|
||||
@@ -165,7 +194,7 @@ first_point(struct lp_setup_context *setup,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
static void
|
||||
lp_setup_reset(struct lp_setup_context *setup)
|
||||
{
|
||||
LP_DBG(DEBUG_SETUP, "%s\n", __func__);
|
||||
@@ -415,6 +444,21 @@ lp_setup_bind_framebuffer(struct lp_setup_context *setup,
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
lp_setup_set_sample_locations(struct lp_setup_context *setup,
|
||||
bool sample_locations_enabled,
|
||||
const uint8_t *sample_locations)
|
||||
{
|
||||
LP_DBG(DEBUG_SETUP, "%s\n", __func__);
|
||||
|
||||
set_scene_state(setup, SETUP_FLUSHED, __func__);
|
||||
|
||||
assert(!setup->scene);
|
||||
|
||||
setup->sample_locations_enabled = sample_locations_enabled;
|
||||
memcpy(setup->sample_locations, sample_locations, sizeof(setup->sample_locations));
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to clear one color buffer of the attached fb, either by binning a clear
|
||||
* command or queuing up the clear for later (when binning is started).
|
||||
|
||||
@@ -45,9 +45,6 @@ struct pipe_fence_handle;
|
||||
struct lp_setup_variant;
|
||||
struct lp_setup_context;
|
||||
|
||||
void
|
||||
lp_setup_reset(struct lp_setup_context *setup);
|
||||
|
||||
struct lp_setup_context *
|
||||
lp_setup_create(struct pipe_context *pipe,
|
||||
struct draw_context *draw);
|
||||
@@ -134,6 +131,11 @@ void
|
||||
lp_setup_set_sample_mask(struct lp_setup_context *setup,
|
||||
uint32_t sample_mask);
|
||||
|
||||
void
|
||||
lp_setup_set_sample_locations(struct lp_setup_context *setup,
|
||||
bool sample_locations_enabled,
|
||||
const uint8_t *sample_locations);
|
||||
|
||||
void
|
||||
lp_setup_set_rasterizer_discard(struct lp_setup_context *setup,
|
||||
bool rasterizer_discard);
|
||||
|
||||
@@ -110,7 +110,8 @@ struct lp_setup_context
|
||||
unsigned multisample:1;
|
||||
unsigned rectangular_lines:1;
|
||||
unsigned cullmode:2; /**< PIPE_FACE_x */
|
||||
unsigned bottom_edge_rule;
|
||||
unsigned bottom_edge_rule:1;
|
||||
unsigned sample_locations_enabled:1;
|
||||
float pixel_offset;
|
||||
float line_width;
|
||||
float point_size;
|
||||
@@ -118,6 +119,7 @@ struct lp_setup_context
|
||||
int8_t viewport_index_slot;
|
||||
int8_t layer_slot;
|
||||
int8_t face_slot;
|
||||
uint8_t sample_locations[LP_MAX_SAMPLES];
|
||||
|
||||
struct pipe_framebuffer_state fb;
|
||||
struct u_rect framebuffer;
|
||||
|
||||
@@ -61,18 +61,19 @@
|
||||
#define LP_NEW_TCS 0x200000
|
||||
#define LP_NEW_TES 0x400000
|
||||
#define LP_NEW_SAMPLE_MASK 0x800000
|
||||
#define LP_NEW_TASK 0x1000000
|
||||
#define LP_NEW_TASK_CONSTANTS 0x2000000
|
||||
#define LP_NEW_TASK_SAMPLER 0x4000000
|
||||
#define LP_NEW_TASK_SAMPLER_VIEW 0x8000000
|
||||
#define LP_NEW_TASK_SSBOS 0x10000000
|
||||
#define LP_NEW_TASK_IMAGES 0x20000000
|
||||
#define LP_NEW_MESH 0x40000000
|
||||
#define LP_NEW_MESH_CONSTANTS 0x80000000
|
||||
#define LP_NEW_MESH_SAMPLER 0x100000000ULL
|
||||
#define LP_NEW_MESH_SAMPLER_VIEW 0x200000000ULL
|
||||
#define LP_NEW_MESH_SSBOS 0x400000000ULL
|
||||
#define LP_NEW_MESH_IMAGES 0x800000000ULL
|
||||
#define LP_NEW_SAMPLE_LOCATIONS 0x1000000
|
||||
#define LP_NEW_TASK 0x2000000
|
||||
#define LP_NEW_TASK_CONSTANTS 0x4000000
|
||||
#define LP_NEW_TASK_SAMPLER 0x8000000
|
||||
#define LP_NEW_TASK_SAMPLER_VIEW 0x10000000
|
||||
#define LP_NEW_TASK_SSBOS 0x20000000
|
||||
#define LP_NEW_TASK_IMAGES 0x40000000
|
||||
#define LP_NEW_MESH 0x80000000
|
||||
#define LP_NEW_MESH_CONSTANTS 0x100000000ULL
|
||||
#define LP_NEW_MESH_SAMPLER 0x200000000ULL
|
||||
#define LP_NEW_MESH_SAMPLER_VIEW 0x400000000ULL
|
||||
#define LP_NEW_MESH_SSBOS 0x800000000ULL
|
||||
#define LP_NEW_MESH_IMAGES 0x1000000000ULL
|
||||
|
||||
#define LP_CSNEW_CS 0x1
|
||||
#define LP_CSNEW_CONSTANTS 0x2
|
||||
|
||||
@@ -197,6 +197,29 @@ llvmpipe_set_min_samples(struct pipe_context *pipe,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
llvmpipe_set_sample_locations(struct pipe_context *pipe,
|
||||
size_t size, const uint8_t *locations)
|
||||
{
|
||||
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
|
||||
|
||||
bool sample_locations_enabled = size && locations;
|
||||
|
||||
assert(size <= sizeof(llvmpipe->sample_locations));
|
||||
if (sample_locations_enabled != llvmpipe->sample_locations_enabled) {
|
||||
llvmpipe->sample_locations_enabled = sample_locations_enabled;
|
||||
llvmpipe->dirty |= LP_NEW_SAMPLE_LOCATIONS;
|
||||
}
|
||||
|
||||
|
||||
if (sample_locations_enabled &&
|
||||
memcmp(locations, llvmpipe->sample_locations, size)) {
|
||||
memcpy(llvmpipe->sample_locations, locations, size);
|
||||
llvmpipe->dirty |= LP_NEW_SAMPLE_LOCATIONS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
llvmpipe_init_blend_funcs(struct llvmpipe_context *llvmpipe)
|
||||
{
|
||||
@@ -213,6 +236,7 @@ llvmpipe_init_blend_funcs(struct llvmpipe_context *llvmpipe)
|
||||
llvmpipe->pipe.set_stencil_ref = llvmpipe_set_stencil_ref;
|
||||
llvmpipe->pipe.set_sample_mask = llvmpipe_set_sample_mask;
|
||||
llvmpipe->pipe.set_min_samples = llvmpipe_set_min_samples;
|
||||
llvmpipe->pipe.set_sample_locations = llvmpipe_set_sample_locations;
|
||||
|
||||
llvmpipe->dirty |= LP_NEW_SAMPLE_MASK;
|
||||
llvmpipe->sample_mask = ~0;
|
||||
|
||||
@@ -306,7 +306,8 @@ llvmpipe_update_derived(struct llvmpipe_context *llvmpipe)
|
||||
LP_NEW_RASTERIZER |
|
||||
LP_NEW_SAMPLER |
|
||||
LP_NEW_SAMPLER_VIEW |
|
||||
LP_NEW_OCCLUSION_QUERY))
|
||||
LP_NEW_OCCLUSION_QUERY |
|
||||
LP_NEW_SAMPLE_LOCATIONS))
|
||||
llvmpipe_update_fs(llvmpipe);
|
||||
|
||||
if (llvmpipe->dirty & (LP_NEW_FS |
|
||||
@@ -331,6 +332,11 @@ llvmpipe_update_derived(struct llvmpipe_context *llvmpipe)
|
||||
lp_setup_set_blend_color(llvmpipe->setup,
|
||||
&llvmpipe->blend_color);
|
||||
|
||||
if (llvmpipe->dirty & LP_NEW_SAMPLE_LOCATIONS)
|
||||
lp_setup_set_sample_locations(llvmpipe->setup,
|
||||
llvmpipe->sample_locations_enabled,
|
||||
llvmpipe->sample_locations);
|
||||
|
||||
if (llvmpipe->dirty & LP_NEW_SCISSOR)
|
||||
lp_setup_set_scissors(llvmpipe->setup, llvmpipe->scissors);
|
||||
|
||||
|
||||
@@ -3362,22 +3362,44 @@ generate_fragment(struct llvmpipe_context *lp,
|
||||
|
||||
if (key->multisample && key->coverage_samples == 4) {
|
||||
LLVMValueRef sample_pos_arr[8];
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
sample_pos_arr[i * 2] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_4x[i][0]);
|
||||
sample_pos_arr[i * 2 + 1] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_4x[i][1]);
|
||||
if (key->sample_locations_enabled) {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
/*
|
||||
* sample_locations holds 4 bit values, just divide by 16
|
||||
* to get subpixel offset as float
|
||||
*/
|
||||
sample_pos_arr[i * 2] = LLVMConstReal(flt_type,
|
||||
(key->sample_locations[i] & 0xF) * 0.0625);
|
||||
sample_pos_arr[i * 2 + 1] = LLVMConstReal(flt_type,
|
||||
(key->sample_locations[i] >> 4) * 0.0625);
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < 4; i++) {
|
||||
sample_pos_arr[i * 2] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_4x[i][0]);
|
||||
sample_pos_arr[i * 2 + 1] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_4x[i][1]);
|
||||
}
|
||||
}
|
||||
sample_pos_array =
|
||||
LLVMConstArray(LLVMFloatTypeInContext(gallivm->context),
|
||||
sample_pos_arr, 8);
|
||||
} else if (key->multisample && key->coverage_samples == 8) {
|
||||
LLVMValueRef sample_pos_arr[16];
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
sample_pos_arr[i * 2] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_8x[i][0]);
|
||||
sample_pos_arr[i * 2 + 1] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_8x[i][1]);
|
||||
if (key->sample_locations_enabled) {
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
sample_pos_arr[i * 2] = LLVMConstReal(flt_type,
|
||||
(key->sample_locations[i] & 0xF) * 0.0625);
|
||||
sample_pos_arr[i * 2 + 1] = LLVMConstReal(flt_type,
|
||||
(key->sample_locations[i] >> 4) * 0.0625);
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < 8; i++) {
|
||||
sample_pos_arr[i * 2] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_8x[i][0]);
|
||||
sample_pos_arr[i * 2 + 1] = LLVMConstReal(flt_type,
|
||||
lp_sample_pos_8x[i][1]);
|
||||
}
|
||||
}
|
||||
sample_pos_array =
|
||||
LLVMConstArray(LLVMFloatTypeInContext(gallivm->context),
|
||||
@@ -3616,6 +3638,15 @@ dump_fs_variant_key(struct lp_fragment_shader_variant_key *key)
|
||||
debug_printf("coverage samples = %d\n", key->coverage_samples);
|
||||
debug_printf("min samples = %d\n", key->min_samples);
|
||||
}
|
||||
|
||||
if (key->sample_locations_enabled) {
|
||||
debug_printf("sample_locations_enabled = 1\n");
|
||||
for (unsigned i = 0; i < LP_MAX_SAMPLES; i++) {
|
||||
debug_printf("sample %d loc x = %d y = %d\n", i,
|
||||
key->sample_locations[i] & 0xF, key->sample_locations[i] >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < key->nr_cbufs; ++i) {
|
||||
debug_printf("cbuf_format[%u] = %s\n", i, util_format_name(key->cbuf_format[i]));
|
||||
debug_printf("cbuf nr_samples[%u] = %d\n", i, key->cbuf_nr_samples[i]);
|
||||
@@ -4538,6 +4569,14 @@ make_variant_key(struct llvmpipe_context *lp,
|
||||
if (lp->min_samples > 1 || nir->info.fs.uses_fbfetch_output)
|
||||
key->min_samples = key->coverage_samples;
|
||||
}
|
||||
|
||||
if (key->multisample) {
|
||||
key->sample_locations_enabled = lp->sample_locations_enabled;
|
||||
if (key->sample_locations_enabled) {
|
||||
memcpy(key->sample_locations, lp->sample_locations, sizeof(key->sample_locations));
|
||||
}
|
||||
}
|
||||
|
||||
key->nr_cbufs = lp->framebuffer.nr_cbufs;
|
||||
|
||||
if (!key->blend.independent_blend_enable) {
|
||||
|
||||
@@ -87,6 +87,7 @@ struct lp_fragment_shader_variant_key
|
||||
unsigned multisample:1;
|
||||
unsigned no_ms_sample_mask_out:1;
|
||||
unsigned restrict_depth_values:1;
|
||||
unsigned sample_locations_enabled:1;
|
||||
|
||||
enum pipe_format zsbuf_format;
|
||||
enum pipe_format cbuf_format[PIPE_MAX_COLOR_BUFS];
|
||||
@@ -95,6 +96,7 @@ struct lp_fragment_shader_variant_key
|
||||
uint8_t zsbuf_nr_samples;
|
||||
uint8_t coverage_samples;
|
||||
uint8_t min_samples;
|
||||
uint8_t sample_locations[LP_MAX_SAMPLES]; /* maybe pass this through scene? */
|
||||
/* followed by variable number of samplers + images */
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user