Commit eb522717 authored by Dave Airlie's avatar Dave Airlie

llvmpipe: add support for tessellation shaders

This adds the hooks between llvmpipe and draw to enable tessellation shaders.

It also updates the CI results and docs.
Reviewed-by: default avatarRoland Scheidegger <sroland@vmware.com>
Tested-by: Marge Bot <mesa/mesa!3841>
Part-of: <mesa/mesa!3841>
parent a3257ae7
Pipeline #113808 passed with stages
in 14 minutes and 42 seconds
This diff is collapsed.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -130,7 +130,7 @@ GL 4.0, GLSL 4.00 --- all DONE: i965/gen7+, nvc0, r600, radeonsi, virgl
GL_ARB_gpu_shader_fp64 DONE (i965/gen7+, llvmpipe, softpipe, swr)
GL_ARB_sample_shading DONE (freedreno/a6xx, i965/gen6+, nv50)
GL_ARB_shader_subroutine DONE (freedreno, i965/gen6+, nv50, llvmpipe, softpipe, swr)
GL_ARB_tessellation_shader DONE (i965/gen7+, swr)
GL_ARB_tessellation_shader DONE (i965/gen7+, llvmpipe, swr)
GL_ARB_texture_buffer_object_rgb32 DONE (freedreno, i965/gen6+, llvmpipe, softpipe, swr)
GL_ARB_texture_cube_map_array DONE (i965/gen6+, nv50, llvmpipe, softpipe, swr)
GL_ARB_texture_gather DONE (freedreno, i965/gen6+, nv50, llvmpipe, softpipe, swr)
......
......@@ -65,6 +65,7 @@ C_SOURCES := \
lp_state_setup.h \
lp_state_so.c \
lp_state_surface.c \
lp_state_tess.c \
lp_state_vertex.c \
lp_state_vs.c \
lp_surface.c \
......
......@@ -176,6 +176,7 @@ llvmpipe_create_context(struct pipe_screen *screen, void *priv,
llvmpipe_init_fs_funcs(llvmpipe);
llvmpipe_init_vs_funcs(llvmpipe);
llvmpipe_init_gs_funcs(llvmpipe);
llvmpipe_init_tess_funcs(llvmpipe);
llvmpipe_init_rasterizer_funcs(llvmpipe);
llvmpipe_init_context_resource_funcs( &llvmpipe->pipe );
llvmpipe_init_surface_functions(llvmpipe);
......
......@@ -67,6 +67,8 @@ struct llvmpipe_context {
struct lp_fragment_shader *fs;
struct draw_vertex_shader *vs;
const struct lp_geometry_shader *gs;
const struct lp_tess_ctrl_shader *tcs;
const struct lp_tess_eval_shader *tes;
struct lp_compute_shader *cs;
const struct lp_velems_state *velems;
const struct lp_so_state *so;
......
......@@ -105,6 +105,12 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
llvmpipe_prepare_geometry_sampling(lp,
lp->num_sampler_views[PIPE_SHADER_GEOMETRY],
lp->sampler_views[PIPE_SHADER_GEOMETRY]);
llvmpipe_prepare_tess_ctrl_sampling(lp,
lp->num_sampler_views[PIPE_SHADER_TESS_CTRL],
lp->sampler_views[PIPE_SHADER_TESS_CTRL]);
llvmpipe_prepare_tess_eval_sampling(lp,
lp->num_sampler_views[PIPE_SHADER_TESS_EVAL],
lp->sampler_views[PIPE_SHADER_TESS_EVAL]);
llvmpipe_prepare_vertex_images(lp,
lp->num_images[PIPE_SHADER_VERTEX],
......@@ -112,6 +118,12 @@ llvmpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
llvmpipe_prepare_geometry_images(lp,
lp->num_images[PIPE_SHADER_GEOMETRY],
lp->images[PIPE_SHADER_GEOMETRY]);
llvmpipe_prepare_tess_ctrl_images(lp,
lp->num_images[PIPE_SHADER_TESS_CTRL],
lp->images[PIPE_SHADER_TESS_CTRL]);
llvmpipe_prepare_tess_eval_images(lp,
lp->num_images[PIPE_SHADER_TESS_EVAL],
lp->images[PIPE_SHADER_TESS_EVAL]);
if (lp->gs && lp->gs->no_tokens) {
/* we have an empty geometry shader with stream output, so
attach the stream output info to the current vertex shader */
......
......@@ -332,10 +332,11 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_MULTI_DRAW_INDIRECT:
case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
return 1;
case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
return 32;
case PIPE_CAP_MULTISAMPLE_Z_RESOLVE:
case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
case PIPE_CAP_DEPTH_BOUNDS_TEST:
case PIPE_CAP_TGSI_TXQS:
case PIPE_CAP_FORCE_PERSAMPLE_INTERP:
......@@ -413,6 +414,7 @@ llvmpipe_get_shader_param(struct pipe_screen *screen,
enum pipe_shader_type shader,
enum pipe_shader_cap param)
{
struct llvmpipe_screen *lscreen = llvmpipe_screen(screen);
switch(shader)
{
case PIPE_SHADER_COMPUTE:
......@@ -420,7 +422,6 @@ llvmpipe_get_shader_param(struct pipe_screen *screen,
return (1 << PIPE_SHADER_IR_TGSI) | (1 << PIPE_SHADER_IR_NIR) | (1 << PIPE_SHADER_IR_NIR_SERIALIZED);
case PIPE_SHADER_FRAGMENT:
if (param == PIPE_SHADER_CAP_PREFERRED_IR) {
struct llvmpipe_screen *lscreen = llvmpipe_screen(screen);
if (lscreen->use_tgsi)
return PIPE_SHADER_IR_TGSI;
else
......@@ -430,10 +431,13 @@ llvmpipe_get_shader_param(struct pipe_screen *screen,
default:
return gallivm_get_shader_param(param);
}
case PIPE_SHADER_TESS_CTRL:
case PIPE_SHADER_TESS_EVAL:
if (lscreen->use_tgsi)
return 0;
case PIPE_SHADER_VERTEX:
case PIPE_SHADER_GEOMETRY:
if (param == PIPE_SHADER_CAP_PREFERRED_IR) {
struct llvmpipe_screen *lscreen = llvmpipe_screen(screen);
if (lscreen->use_tgsi)
return PIPE_SHADER_IR_TGSI;
else
......
......@@ -58,6 +58,8 @@
#define LP_NEW_SO_BUFFERS 0x40000
#define LP_NEW_FS_SSBOS 0x80000
#define LP_NEW_FS_IMAGES 0x100000
#define LP_NEW_TCS 0x200000
#define LP_NEW_TES 0x400000
#define LP_CSNEW_CS 0x1
#define LP_CSNEW_CONSTANTS 0x2
......@@ -78,6 +80,19 @@ struct lp_geometry_shader {
struct draw_geometry_shader *dgs;
};
struct lp_tess_ctrl_shader {
boolean no_tokens;
struct pipe_stream_output_info stream_output;
struct draw_tess_ctrl_shader *dtcs;
};
struct lp_tess_eval_shader {
boolean no_tokens;
struct pipe_stream_output_info stream_output;
struct draw_tess_eval_shader *dtes;
};
/** Vertex element state */
struct lp_velems_state
{
......@@ -130,6 +145,9 @@ llvmpipe_init_vs_funcs(struct llvmpipe_context *llvmpipe);
void
llvmpipe_init_gs_funcs(struct llvmpipe_context *llvmpipe);
void
llvmpipe_init_tess_funcs(struct llvmpipe_context *llvmpipe);
void
llvmpipe_init_rasterizer_funcs(struct llvmpipe_context *llvmpipe);
......@@ -146,6 +164,16 @@ llvmpipe_prepare_geometry_sampling(struct llvmpipe_context *ctx,
unsigned num,
struct pipe_sampler_view **views);
void
llvmpipe_prepare_tess_ctrl_sampling(struct llvmpipe_context *ctx,
unsigned num,
struct pipe_sampler_view **views);
void
llvmpipe_prepare_tess_eval_sampling(struct llvmpipe_context *ctx,
unsigned num,
struct pipe_sampler_view **views);
void
llvmpipe_prepare_vertex_images(struct llvmpipe_context *lp,
unsigned num,
......@@ -155,4 +183,15 @@ void
llvmpipe_prepare_geometry_images(struct llvmpipe_context *lp,
unsigned num,
struct pipe_image_view *views);
void
llvmpipe_prepare_tess_ctrl_images(struct llvmpipe_context *lp,
unsigned num,
struct pipe_image_view *views);
void
llvmpipe_prepare_tess_eval_images(struct llvmpipe_context *lp,
unsigned num,
struct pipe_image_view *views);
#endif
......@@ -195,6 +195,8 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
if (llvmpipe->dirty & (LP_NEW_RASTERIZER |
LP_NEW_FS |
LP_NEW_GS |
LP_NEW_TCS |
LP_NEW_TES |
LP_NEW_VS))
compute_vertex_info(llvmpipe);
......
......@@ -3167,7 +3167,9 @@ llvmpipe_set_constant_buffer(struct pipe_context *pipe,
}
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;
......@@ -3212,7 +3214,9 @@ llvmpipe_set_shader_buffers(struct pipe_context *pipe,
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)
......@@ -3246,7 +3250,9 @@ llvmpipe_set_shader_images(struct pipe_context *pipe,
llvmpipe->num_images[shader] = start_slot + count;
if (shader == PIPE_SHADER_VERTEX ||
shader == PIPE_SHADER_GEOMETRY) {
shader == PIPE_SHADER_GEOMETRY ||
shader == PIPE_SHADER_TESS_CTRL ||
shader == PIPE_SHADER_TESS_EVAL) {
draw_set_images(llvmpipe->draw,
shader,
llvmpipe->images[shader],
......
......@@ -92,7 +92,10 @@ llvmpipe_bind_sampler_states(struct pipe_context *pipe,
llvmpipe->num_samplers[shader] = j;
}
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
if (shader == PIPE_SHADER_VERTEX ||
shader == PIPE_SHADER_GEOMETRY ||
shader == PIPE_SHADER_TESS_CTRL ||
shader == PIPE_SHADER_TESS_EVAL) {
draw_set_samplers(llvmpipe->draw,
shader,
llvmpipe->samplers[shader],
......@@ -146,7 +149,10 @@ llvmpipe_set_sampler_views(struct pipe_context *pipe,
llvmpipe->num_sampler_views[shader] = j;
}
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
if (shader == PIPE_SHADER_VERTEX ||
shader == PIPE_SHADER_GEOMETRY ||
shader == PIPE_SHADER_TESS_CTRL ||
shader == PIPE_SHADER_TESS_EVAL) {
draw_set_sampler_views(llvmpipe->draw,
shader,
llvmpipe->sampler_views[shader],
......@@ -360,6 +366,28 @@ llvmpipe_prepare_geometry_sampling(struct llvmpipe_context *lp,
prepare_shader_sampling(lp, num, views, PIPE_SHADER_GEOMETRY);
}
/**
* Called whenever we're about to draw (no dirty flag, FIXME?).
*/
void
llvmpipe_prepare_tess_ctrl_sampling(struct llvmpipe_context *lp,
unsigned num,
struct pipe_sampler_view **views)
{
prepare_shader_sampling(lp, num, views, PIPE_SHADER_TESS_CTRL);
}
/**
* Called whenever we're about to draw (no dirty flag, FIXME?).
*/
void
llvmpipe_prepare_tess_eval_sampling(struct llvmpipe_context *lp,
unsigned num,
struct pipe_sampler_view **views)
{
prepare_shader_sampling(lp, num, views, PIPE_SHADER_TESS_EVAL);
}
static void
prepare_shader_images(
struct llvmpipe_context *lp,
......@@ -472,6 +500,28 @@ llvmpipe_prepare_geometry_images(struct llvmpipe_context *lp,
prepare_shader_images(lp, num, views, PIPE_SHADER_GEOMETRY);
}
/**
* Called whenever we're about to draw (no dirty flag, FIXME?).
*/
void
llvmpipe_prepare_tess_ctrl_images(struct llvmpipe_context *lp,
unsigned num,
struct pipe_image_view *views)
{
prepare_shader_images(lp, num, views, PIPE_SHADER_TESS_CTRL);
}
/**
* Called whenever we're about to draw (no dirty flag, FIXME?).
*/
void
llvmpipe_prepare_tess_eval_images(struct llvmpipe_context *lp,
unsigned num,
struct pipe_image_view *views)
{
prepare_shader_images(lp, num, views, PIPE_SHADER_TESS_EVAL);
}
void
llvmpipe_init_sampler_funcs(struct llvmpipe_context *llvmpipe)
{
......
/**************************************************************************
*
* Copyright 2019 Red Hat.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
**************************************************************************/
#include "lp_context.h"
#include "lp_state.h"
#include "lp_texture.h"
#include "lp_debug.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "draw/draw_context.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_parse.h"
static void *
llvmpipe_create_tcs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_tess_ctrl_shader *state;
state = CALLOC_STRUCT(lp_tess_ctrl_shader);
if (!state)
goto no_state;
/* debug */
if (LP_DEBUG & DEBUG_TGSI) {
debug_printf("llvmpipe: Create tess ctrl shader %p:\n", (void *)state);
tgsi_dump(templ->tokens, 0);
}
/* copy stream output info */
state->no_tokens = !templ->tokens;
memcpy(&state->stream_output, &templ->stream_output, sizeof state->stream_output);
if (templ->tokens || templ->type == PIPE_SHADER_IR_NIR) {
state->dtcs = draw_create_tess_ctrl_shader(llvmpipe->draw, templ);
if (state->dtcs == NULL) {
goto no_dgs;
}
}
return state;
no_dgs:
FREE( state );
no_state:
return NULL;
}
static void
llvmpipe_bind_tcs_state(struct pipe_context *pipe, void *tcs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
llvmpipe->tcs = (struct lp_tess_ctrl_shader *)tcs;
draw_bind_tess_ctrl_shader(llvmpipe->draw,
(llvmpipe->tcs ? llvmpipe->tcs->dtcs : NULL));
llvmpipe->dirty |= LP_NEW_TCS;
}
static void
llvmpipe_delete_tcs_state(struct pipe_context *pipe, void *tcs)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_tess_ctrl_shader *state =
(struct lp_tess_ctrl_shader *)tcs;
if (!state) {
return;
}
draw_delete_tess_ctrl_shader(llvmpipe->draw, state->dtcs);
FREE(state);
}
static void *
llvmpipe_create_tes_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_tess_eval_shader *state;
state = CALLOC_STRUCT(lp_tess_eval_shader);
if (!state)
goto no_state;
/* debug */
if (LP_DEBUG & DEBUG_TGSI) {
debug_printf("llvmpipe: Create tess eval shader %p:\n", (void *)state);
tgsi_dump(templ->tokens, 0);
}
/* copy stream output info */
state->no_tokens = !templ->tokens;
memcpy(&state->stream_output, &templ->stream_output, sizeof state->stream_output);
if (templ->tokens || templ->type == PIPE_SHADER_IR_NIR) {
state->dtes = draw_create_tess_eval_shader(llvmpipe->draw, templ);
if (state->dtes == NULL) {
goto no_dgs;
}
}
return state;
no_dgs:
FREE( state );
no_state:
return NULL;
}
static void
llvmpipe_bind_tes_state(struct pipe_context *pipe, void *tes)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
llvmpipe->tes = (struct lp_tess_eval_shader *)tes;
draw_bind_tess_eval_shader(llvmpipe->draw,
(llvmpipe->tes ? llvmpipe->tes->dtes : NULL));
llvmpipe->dirty |= LP_NEW_TES;
}
static void
llvmpipe_delete_tes_state(struct pipe_context *pipe, void *tes)
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
struct lp_tess_eval_shader *state =
(struct lp_tess_eval_shader *)tes;
if (!state) {
return;
}
draw_delete_tess_eval_shader(llvmpipe->draw, state->dtes);
FREE(state);
}
static void
llvmpipe_set_tess_state(struct pipe_context *pipe,
const float default_outer_level[4],
const float default_inner_level[2])
{
struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
draw_set_tess_state(llvmpipe->draw, default_outer_level, default_inner_level);
}
void
llvmpipe_init_tess_funcs(struct llvmpipe_context *llvmpipe)
{
llvmpipe->pipe.create_tcs_state = llvmpipe_create_tcs_state;
llvmpipe->pipe.bind_tcs_state = llvmpipe_bind_tcs_state;
llvmpipe->pipe.delete_tcs_state = llvmpipe_delete_tcs_state;
llvmpipe->pipe.create_tes_state = llvmpipe_create_tes_state;
llvmpipe->pipe.bind_tes_state = llvmpipe_bind_tes_state;
llvmpipe->pipe.delete_tes_state = llvmpipe_delete_tes_state;
llvmpipe->pipe.set_tess_state = llvmpipe_set_tess_state;
}
......@@ -102,6 +102,8 @@ static void lp_blit(struct pipe_context *pipe,
util_blitter_save_scissor(lp->blitter, &lp->scissors[0]);
util_blitter_save_fragment_shader(lp->blitter, lp->fs);
util_blitter_save_blend(lp->blitter, (void*)lp->blend);
util_blitter_save_tessctrl_shader(lp->blitter, (void*)lp->tcs);
util_blitter_save_tesseval_shader(lp->blitter, (void*)lp->tes);
util_blitter_save_depth_stencil_alpha(lp->blitter, (void*)lp->depth_stencil);
util_blitter_save_stencil_ref(lp->blitter, &lp->stencil_ref);
/*util_blitter_save_sample_mask(sp->blitter, lp->sample_mask);*/
......
......@@ -85,6 +85,7 @@ files_llvmpipe = files(
'lp_state_setup.h',
'lp_state_so.c',
'lp_state_surface.c',
'lp_state_tess.c',
'lp_state_vertex.c',
'lp_state_vs.c',
'lp_surface.c',
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment