svga: Add GL4.1(compatibility profile) support in svga driver

This patch is a squash commit of a very long in-house patch series.

Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Charmaine Lee <charmainel@vmware.com>
Signed-off-by: Neha Bhende <bhenden@vmware.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5317>
This commit is contained in:
Neha Bhende 2020-05-26 21:26:42 +05:30 committed by Marge Bot
parent 52ce25be87
commit ccb4ea5a43
61 changed files with 8067 additions and 1555 deletions

View File

@ -201,7 +201,7 @@ typedef enum {
VGPU10_OPCODE_DCL_GLOBAL_FLAGS = 106, VGPU10_OPCODE_DCL_GLOBAL_FLAGS = 106,
/* GL guest */ /* GL guest */
VGPU10_OPCODE_IDIV = 107, VGPU10_OPCODE_VMWARE = 107,
/* DX10.1 */ /* DX10.1 */
VGPU10_OPCODE_LOD = 108, VGPU10_OPCODE_LOD = 108,

View File

@ -436,8 +436,9 @@ typedef uint32 SVGA3dSurfaceFlags;
* mob-backing to store all the samples. * mob-backing to store all the samples.
*/ */
#define SVGA3D_SURFACE_MULTISAMPLE (CONST64U(1) << 32) #define SVGA3D_SURFACE_MULTISAMPLE (CONST64U(1) << 32)
#define SVGA3D_SURFACE_DRAWINDIRECT_ARGS (CONST64U(1) << 38)
#define SVGA3D_SURFACE_FLAG_MAX (CONST64U(1) << 33) #define SVGA3D_SURFACE_FLAG_MAX (CONST64U(1) << 42)
/* /*
* Surface flags types: * Surface flags types:
@ -464,7 +465,8 @@ typedef uint64 SVGA3dSurfaceAllFlags;
SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \ SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \
SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
SVGA3D_SURFACE_VADECODE | \ SVGA3D_SURFACE_VADECODE | \
SVGA3D_SURFACE_MULTISAMPLE \ SVGA3D_SURFACE_MULTISAMPLE | \
SVGA3D_SURFACE_DRAWINDIRECT_ARGS \
) )
#define SVGA3D_SURFACE_2D_DISALLOWED_MASK \ #define SVGA3D_SURFACE_2D_DISALLOWED_MASK \
@ -480,7 +482,8 @@ typedef uint64 SVGA3dSurfaceAllFlags;
SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \ SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
SVGA3D_SURFACE_VADECODE | \ SVGA3D_SURFACE_VADECODE | \
SVGA3D_SURFACE_MULTISAMPLE \ SVGA3D_SURFACE_MULTISAMPLE | \
SVGA3D_SURFACE_DRAWINDIRECT_ARGS \
) )
#define SVGA3D_SURFACE_BASICOPS_DISALLOWED_MASK \ #define SVGA3D_SURFACE_BASICOPS_DISALLOWED_MASK \
@ -508,7 +511,8 @@ typedef uint64 SVGA3dSurfaceAllFlags;
SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \ SVGA3D_SURFACE_HINT_INDIRECT_UPDATE | \
SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
SVGA3D_SURFACE_VADECODE | \ SVGA3D_SURFACE_VADECODE | \
SVGA3D_SURFACE_MULTISAMPLE \ SVGA3D_SURFACE_MULTISAMPLE | \
SVGA3D_SURFACE_DRAWINDIRECT_ARGS \
) )
#define SVGA3D_SURFACE_BUFFER_DISALLOWED_MASK \ #define SVGA3D_SURFACE_BUFFER_DISALLOWED_MASK \
@ -527,7 +531,8 @@ typedef uint64 SVGA3dSurfaceAllFlags;
SVGA3D_SURFACE_VOLUME | \ SVGA3D_SURFACE_VOLUME | \
SVGA3D_SURFACE_1D | \ SVGA3D_SURFACE_1D | \
SVGA3D_SURFACE_SCREENTARGET | \ SVGA3D_SURFACE_SCREENTARGET | \
SVGA3D_SURFACE_MOB_PITCH \ SVGA3D_SURFACE_MOB_PITCH | \
SVGA3D_SURFACE_DRAWINDIRECT_ARGS \
) )
#define SVGA3D_SURFACE_DX_ONLY_MASK \ #define SVGA3D_SURFACE_DX_ONLY_MASK \
@ -636,7 +641,8 @@ typedef uint64 SVGA3dSurfaceAllFlags;
SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \ SVGA3D_SURFACE_BIND_STREAM_OUTPUT | \
SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \ SVGA3D_SURFACE_TRANSFER_FROM_BUFFER | \
SVGA3D_SURFACE_VADECODE | \ SVGA3D_SURFACE_VADECODE | \
SVGA3D_SURFACE_MULTISAMPLE \ SVGA3D_SURFACE_MULTISAMPLE | \
SVGA3D_SURFACE_DRAWINDIRECT_ARGS \
) )

View File

@ -36,6 +36,7 @@ files_svga = files(
'svga_pipe_flush.c', 'svga_pipe_flush.c',
'svga_pipe_fs.c', 'svga_pipe_fs.c',
'svga_pipe_gs.c', 'svga_pipe_gs.c',
'svga_pipe_ts.c',
'svga_pipe_misc.c', 'svga_pipe_misc.c',
'svga_pipe_query.c', 'svga_pipe_query.c',
'svga_pipe_rasterizer.c', 'svga_pipe_rasterizer.c',
@ -56,6 +57,7 @@ files_svga = files(
'svga_state_framebuffer.c', 'svga_state_framebuffer.c',
'svga_state_fs.c', 'svga_state_fs.c',
'svga_state_gs.c', 'svga_state_gs.c',
'svga_state_ts.c',
'svga_state_need_swtnl.c', 'svga_state_need_swtnl.c',
'svga_state_rss.c', 'svga_state_rss.c',
'svga_state_sampler.c', 'svga_state_sampler.c',

View File

@ -697,4 +697,33 @@ SVGA3D_vgpu10_ResolveCopy(struct svga_winsys_context *swc,
struct svga_winsys_surface *src, struct svga_winsys_surface *src,
const SVGA3dSurfaceFormat copyFormat); const SVGA3dSurfaceFormat copyFormat);
enum pipe_error
SVGA3D_sm5_DrawIndexedInstancedIndirect(struct svga_winsys_context *swc,
struct svga_winsys_surface *argBuffer,
unsigned argOffset);
enum pipe_error
SVGA3D_sm5_DrawInstancedIndirect(struct svga_winsys_context *swc,
struct svga_winsys_surface *argBuffer,
unsigned argOffset);
enum pipe_error
SVGA3D_sm5_Dispatch(struct svga_winsys_context *swc,
const uint32 threadGroupCount[3]);
enum pipe_error
SVGA3D_sm5_DispatchIndirect(struct svga_winsys_context *swc,
struct svga_winsys_surface *argBuffer,
uint32 argOffset);
enum pipe_error
SVGA3D_sm5_DefineAndBindStreamOutput(struct svga_winsys_context *swc,
SVGA3dStreamOutputId soid,
uint32 numOutputStreamEntries,
uint32 numOutputStreamStrides,
uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS],
struct svga_winsys_buffer *declBuf,
uint32 rasterizedStream,
uint32 sizeInBytes);
#endif /* __SVGA3D_H__ */ #endif /* __SVGA3D_H__ */

View File

@ -1130,7 +1130,7 @@ SVGA3D_vgpu10_DefineStreamOutput(struct svga_winsys_context *swc,
memcpy(cmd->decl, decl, memcpy(cmd->decl, decl,
sizeof(SVGA3dStreamOutputDeclarationEntry) sizeof(SVGA3dStreamOutputDeclarationEntry)
* SVGA3D_MAX_STREAMOUT_DECLS); * SVGA3D_MAX_DX10_STREAMOUT_DECLS);
cmd->rasterizedStream = 0; cmd->rasterizedStream = 0;
swc->commit(swc); swc->commit(swc);
@ -1432,3 +1432,159 @@ SVGA3D_vgpu10_ResolveCopy(struct svga_winsys_context *swc,
return PIPE_OK; return PIPE_OK;
} }
enum pipe_error
SVGA3D_sm5_DrawIndexedInstancedIndirect(struct svga_winsys_context *swc,
struct svga_winsys_surface *argBuffer,
unsigned argOffset)
{
SVGA3dCmdDXDrawIndexedInstancedIndirect *cmd =
SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT,
sizeof(SVGA3dCmdDXDrawIndexedInstancedIndirect),
1); /* one relocation */
if (!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
swc->surface_relocation(swc, &cmd->argsBufferSid, NULL, argBuffer,
SVGA_RELOC_READ);
cmd->byteOffsetForArgs = argOffset;
swc->commit(swc);
return PIPE_OK;
}
enum pipe_error
SVGA3D_sm5_DrawInstancedIndirect(struct svga_winsys_context *swc,
struct svga_winsys_surface *argBuffer,
unsigned argOffset)
{
SVGA3dCmdDXDrawInstancedIndirect *cmd =
SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT,
sizeof(SVGA3dCmdDXDrawInstancedIndirect),
1); /* one relocation */
if (!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
swc->surface_relocation(swc, &cmd->argsBufferSid, NULL, argBuffer,
SVGA_RELOC_READ);
cmd->byteOffsetForArgs = argOffset;
swc->commit(swc);
return PIPE_OK;
}
enum pipe_error
SVGA3D_sm5_Dispatch(struct svga_winsys_context *swc,
const uint32 threadGroupCount[3])
{
SVGA3dCmdDXDispatch *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_DX_DISPATCH,
sizeof(SVGA3dCmdDXDispatch),
0);
if (!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
cmd->threadGroupCountX = threadGroupCount[0];
cmd->threadGroupCountY = threadGroupCount[1];
cmd->threadGroupCountZ = threadGroupCount[2];
swc->commit(swc);
return PIPE_OK;
}
enum pipe_error
SVGA3D_sm5_DispatchIndirect(struct svga_winsys_context *swc,
struct svga_winsys_surface *argBuffer,
uint32 argOffset)
{
SVGA3dCmdDXDispatchIndirect *cmd;
cmd = SVGA3D_FIFOReserve(swc,
SVGA_3D_CMD_DX_DISPATCH_INDIRECT,
sizeof(SVGA3dCmdDXDispatchIndirect),
1);
if (!cmd)
return PIPE_ERROR_OUT_OF_MEMORY;
swc->surface_relocation(swc, &cmd->argsBufferSid, NULL, argBuffer,
SVGA_RELOC_READ);
cmd->byteOffsetForArgs = argOffset;
swc->commit(swc);
return PIPE_OK;
}
/**
* We don't want any flush between DefineStreamOutputWithMob and
* BindStreamOutput because it will cause partial state in command
* buffer. This function make that sure there is enough room for
* both commands before issuing them
*/
enum pipe_error
SVGA3D_sm5_DefineAndBindStreamOutput(struct svga_winsys_context *swc,
SVGA3dStreamOutputId soid,
uint32 numOutputStreamEntries,
uint32 numOutputStreamStrides,
uint32 streamOutputStrideInBytes[SVGA3D_DX_MAX_SOTARGETS],
struct svga_winsys_buffer *declBuf,
uint32 rasterizedStream,
uint32 sizeInBytes)
{
unsigned i;
SVGA3dCmdHeader *header;
SVGA3dCmdDXDefineStreamOutputWithMob *dcmd;
SVGA3dCmdDXBindStreamOutput *bcmd;
unsigned totalSize = 2 * sizeof(*header) +
sizeof(*dcmd) + sizeof(*bcmd);
/* Make sure there is room for both commands */
header = swc->reserve(swc, totalSize, 2);
if (!header)
return PIPE_ERROR_OUT_OF_MEMORY;
/* DXDefineStreamOutputWithMob command */
header->id = SVGA_3D_CMD_DX_DEFINE_STREAMOUTPUT_WITH_MOB;
header->size = sizeof(*dcmd);
dcmd = (SVGA3dCmdDXDefineStreamOutputWithMob *)(header + 1);
dcmd->soid= soid;
dcmd->numOutputStreamEntries = numOutputStreamEntries;
dcmd->numOutputStreamStrides = numOutputStreamStrides;
dcmd->rasterizedStream = rasterizedStream;
for (i = 0; i < ARRAY_SIZE(dcmd->streamOutputStrideInBytes); i++)
dcmd->streamOutputStrideInBytes[i] = streamOutputStrideInBytes[i];
/* DXBindStreamOutput command */
header = (SVGA3dCmdHeader *)(dcmd + 1);
header->id = SVGA_3D_CMD_DX_BIND_STREAMOUTPUT;
header->size = sizeof(*bcmd);
bcmd = (SVGA3dCmdDXBindStreamOutput *)(header + 1);
bcmd->soid = soid;
bcmd->offsetInBytes = 0;
swc->mob_relocation(swc, &bcmd->mobid,
&bcmd->offsetInBytes, declBuf, 0,
SVGA_RELOC_WRITE);
bcmd->sizeInBytes = sizeInBytes;
bcmd->offsetInBytes = 0;
swc->commit(swc);
return PIPE_OK;
}

View File

@ -44,6 +44,7 @@
#include "svga_debug.h" #include "svga_debug.h"
#include "svga_state.h" #include "svga_state.h"
#include "svga_winsys.h" #include "svga_winsys.h"
#include "svga_streamout.h"
#define CONST0_UPLOAD_DEFAULT_SIZE 65536 #define CONST0_UPLOAD_DEFAULT_SIZE 65536
@ -79,6 +80,9 @@ svga_destroy(struct pipe_context *pipe)
pipe->delete_blend_state(pipe, svga->noop_blend); pipe->delete_blend_state(pipe, svga->noop_blend);
/* destroy stream output statistics queries */
svga_destroy_stream_output_queries(svga);
/* free query gb object */ /* free query gb object */
if (svga->gb_query) { if (svga->gb_query) {
pipe->destroy_query(pipe, NULL); pipe->destroy_query(pipe, NULL);
@ -91,6 +95,7 @@ svga_destroy(struct pipe_context *pipe)
svga_cleanup_framebuffer(svga); svga_cleanup_framebuffer(svga);
svga_cleanup_tss_binding(svga); svga_cleanup_tss_binding(svga);
svga_cleanup_vertex_state(svga); svga_cleanup_vertex_state(svga);
svga_cleanup_tcs_state(svga);
svga_destroy_swtnl(svga); svga_destroy_swtnl(svga);
svga_hwtnl_destroy(svga->hwtnl); svga_hwtnl_destroy(svga->hwtnl);
@ -174,12 +179,14 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags)
svga_init_fs_functions(svga); svga_init_fs_functions(svga);
svga_init_vs_functions(svga); svga_init_vs_functions(svga);
svga_init_gs_functions(svga); svga_init_gs_functions(svga);
svga_init_ts_functions(svga);
svga_init_vertex_functions(svga); svga_init_vertex_functions(svga);
svga_init_constbuffer_functions(svga); svga_init_constbuffer_functions(svga);
svga_init_query_functions(svga); svga_init_query_functions(svga);
svga_init_surface_functions(svga); svga_init_surface_functions(svga);
svga_init_stream_output_functions(svga); svga_init_stream_output_functions(svga);
svga_init_clear_functions(svga); svga_init_clear_functions(svga);
svga_init_tracked_state(svga);
/* init misc state */ /* init misc state */
svga->curr.sample_mask = ~0; svga->curr.sample_mask = ~0;
@ -250,6 +257,7 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags)
memset(&svga->state.hw_clear, 0xcd, sizeof(svga->state.hw_clear)); memset(&svga->state.hw_clear, 0xcd, sizeof(svga->state.hw_clear));
memset(&svga->state.hw_clear.framebuffer, 0x0, memset(&svga->state.hw_clear.framebuffer, 0x0,
sizeof(svga->state.hw_clear.framebuffer)); sizeof(svga->state.hw_clear.framebuffer));
memset(&svga->state.hw_clear.rtv, 0, sizeof(svga->state.hw_clear.rtv));
svga->state.hw_clear.num_rendertargets = 0; svga->state.hw_clear.num_rendertargets = 0;
svga->state.hw_clear.dsv = NULL; svga->state.hw_clear.dsv = NULL;
@ -269,6 +277,8 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags)
svga->state.hw_draw.vs = NULL; svga->state.hw_draw.vs = NULL;
svga->state.hw_draw.gs = NULL; svga->state.hw_draw.gs = NULL;
svga->state.hw_draw.fs = NULL; svga->state.hw_draw.fs = NULL;
svga->state.hw_draw.tcs = NULL;
svga->state.hw_draw.tes = NULL;
/* Initialize the currently bound buffer resources */ /* Initialize the currently bound buffer resources */
memset(svga->state.hw_draw.constbuf, 0, memset(svga->state.hw_draw.constbuf, 0,
@ -303,10 +313,16 @@ svga_context_create(struct pipe_screen *screen, void *priv, unsigned flags)
svga->noop_blend = svga->pipe.create_blend_state(&svga->pipe, &noop_tmpl); svga->noop_blend = svga->pipe.create_blend_state(&svga->pipe, &noop_tmpl);
} }
svga->dirty = ~0; svga->dirty = SVGA_NEW_ALL;
svga->pred.query_id = SVGA3D_INVALID_ID; svga->pred.query_id = SVGA3D_INVALID_ID;
svga->disable_rasterizer = FALSE; svga->disable_rasterizer = FALSE;
/**
* Create stream output statistics queries used in the workaround for auto
* draw with stream instancing.
*/
svga_create_stream_output_queries(svga);
goto done; goto done;
cleanup: cleanup:
@ -398,6 +414,11 @@ svga_context_flush(struct svga_context *svga,
svga->rebind.flags.fs = TRUE; svga->rebind.flags.fs = TRUE;
svga->rebind.flags.gs = TRUE; svga->rebind.flags.gs = TRUE;
if (svga_have_sm5(svga)) {
svga->rebind.flags.tcs = TRUE;
svga->rebind.flags.tes = TRUE;
}
if (svga_need_to_rebind_resources(svga)) { if (svga_need_to_rebind_resources(svga)) {
svga->rebind.flags.query = TRUE; svga->rebind.flags.query = TRUE;
} }
@ -447,12 +468,7 @@ svga_hwtnl_flush_retry(struct svga_context *svga)
{ {
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
ret = svga_hwtnl_flush(svga->hwtnl); SVGA_RETRY_OOM(svga, ret, svga_hwtnl_flush(svga->hwtnl));
if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
svga_context_flush(svga, NULL);
ret = svga_hwtnl_flush(svga->hwtnl);
}
assert(ret == PIPE_OK); assert(ret == PIPE_OK);
} }

View File

@ -43,7 +43,7 @@
#include "svga_winsys.h" #include "svga_winsys.h"
#include "svga_hw_reg.h" #include "svga_hw_reg.h"
#include "svga3d_shaderdefs.h" #include "svga3d_shaderdefs.h"
#include "svga_debug.h"
/** Non-GPU queries for gallium HUD */ /** Non-GPU queries for gallium HUD */
enum svga_hud { enum svga_hud {
@ -56,6 +56,7 @@ enum svga_hud {
SVGA_QUERY_NUM_BUFFERS_MAPPED, SVGA_QUERY_NUM_BUFFERS_MAPPED,
SVGA_QUERY_NUM_TEXTURES_MAPPED, SVGA_QUERY_NUM_TEXTURES_MAPPED,
SVGA_QUERY_NUM_BYTES_UPLOADED, SVGA_QUERY_NUM_BYTES_UPLOADED,
SVGA_QUERY_NUM_COMMAND_BUFFERS,
SVGA_QUERY_COMMAND_BUFFER_SIZE, SVGA_QUERY_COMMAND_BUFFER_SIZE,
SVGA_QUERY_FLUSH_TIME, SVGA_QUERY_FLUSH_TIME,
SVGA_QUERY_SURFACE_WRITE_FLUSHES, SVGA_QUERY_SURFACE_WRITE_FLUSHES,
@ -64,6 +65,8 @@ enum svga_hud {
SVGA_QUERY_NUM_BUFFER_UPLOADS, SVGA_QUERY_NUM_BUFFER_UPLOADS,
SVGA_QUERY_NUM_CONST_BUF_UPDATES, SVGA_QUERY_NUM_CONST_BUF_UPDATES,
SVGA_QUERY_NUM_CONST_UPDATES, SVGA_QUERY_NUM_CONST_UPDATES,
SVGA_QUERY_NUM_SHADER_RELOCATIONS,
SVGA_QUERY_NUM_SURFACE_RELOCATIONS,
/* running total counters */ /* running total counters */
SVGA_QUERY_MEMORY_USED, SVGA_QUERY_MEMORY_USED,
@ -74,6 +77,7 @@ enum svga_hud {
SVGA_QUERY_NUM_GENERATE_MIPMAP, SVGA_QUERY_NUM_GENERATE_MIPMAP,
SVGA_QUERY_NUM_FAILED_ALLOCATIONS, SVGA_QUERY_NUM_FAILED_ALLOCATIONS,
SVGA_QUERY_NUM_COMMANDS_PER_DRAW, SVGA_QUERY_NUM_COMMANDS_PER_DRAW,
SVGA_QUERY_SHADER_MEM_USED,
/*SVGA_QUERY_MAX has to be last because it is size of an array*/ /*SVGA_QUERY_MAX has to be last because it is size of an array*/
SVGA_QUERY_MAX SVGA_QUERY_MAX
@ -109,6 +113,8 @@ struct svga_blend_state {
unsigned alpha_to_coverage:1; unsigned alpha_to_coverage:1;
unsigned alpha_to_one:1; unsigned alpha_to_one:1;
unsigned blend_color_alpha:1; /**< set blend color to alpha value */ unsigned blend_color_alpha:1; /**< set blend color to alpha value */
unsigned logicop_enabled:1;
unsigned logicop_mode:5;
/** Per-render target state */ /** Per-render target state */
struct { struct {
@ -269,6 +275,11 @@ struct svga_state
struct svga_vertex_shader *vs; struct svga_vertex_shader *vs;
struct svga_geometry_shader *user_gs; /* user-specified GS */ struct svga_geometry_shader *user_gs; /* user-specified GS */
struct svga_geometry_shader *gs; /* derived GS */ struct svga_geometry_shader *gs; /* derived GS */
/* derived tessellation control shader */
struct svga_tcs_shader *tcs;
/* derived tessellation evaluation shader */
struct svga_tes_shader *tes;
struct svga_compute_shader *cs;
struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS]; struct pipe_vertex_buffer vb[PIPE_MAX_ATTRIBS];
/** Constant buffers for each shader. /** Constant buffers for each shader.
@ -286,11 +297,11 @@ struct svga_state
int nr_fbs; int nr_fbs;
struct pipe_poly_stipple poly_stipple; struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor; struct pipe_scissor_state scissor[SVGA3D_DX_MAX_VIEWPORTS];
struct pipe_blend_color blend_color; struct pipe_blend_color blend_color;
struct pipe_stencil_ref stencil_ref; struct pipe_stencil_ref stencil_ref;
struct pipe_clip_state clip; struct pipe_clip_state clip;
struct pipe_viewport_state viewport; struct pipe_viewport_state viewport[SVGA3D_DX_MAX_VIEWPORTS];
unsigned num_samplers[PIPE_SHADER_TYPES]; unsigned num_samplers[PIPE_SHADER_TYPES];
unsigned num_sampler_views[PIPE_SHADER_TYPES]; unsigned num_sampler_views[PIPE_SHADER_TYPES];
@ -303,6 +314,14 @@ struct svga_state
} tex_flags; } tex_flags;
unsigned sample_mask; unsigned sample_mask;
unsigned vertices_per_patch;
float default_tesslevels[6]; /* tessellation (outer[4] + inner[2]) levels */
struct {
/* Determine the layout of the grid (in block units) to be used. */
unsigned size[3];
/* If DispatchIndirect is used, this will has grid size info*/
struct pipe_resource *indirect;
} grid_info;
}; };
struct svga_prescale { struct svga_prescale {
@ -311,21 +330,27 @@ struct svga_prescale {
boolean enabled; boolean enabled;
}; };
struct svga_depthrange {
float zmin;
float zmax;
};
/* Updated by calling svga_update_state( SVGA_STATE_HW_CLEAR ) /* Updated by calling svga_update_state( SVGA_STATE_HW_CLEAR )
*/ */
struct svga_hw_clear_state struct svga_hw_clear_state
{ {
SVGA3dRect viewport;
struct {
float zmin, zmax;
} depthrange;
struct pipe_framebuffer_state framebuffer; struct pipe_framebuffer_state framebuffer;
struct svga_prescale prescale;
/* VGPU9 only */
SVGA3dRect viewport;
struct svga_depthrange depthrange;
/* VGPU10 state */ /* VGPU10 state */
SVGA3dViewport viewports[SVGA3D_DX_MAX_VIEWPORTS];
struct svga_prescale prescale[SVGA3D_DX_MAX_VIEWPORTS];
struct pipe_scissor_state scissors[SVGA3D_DX_MAX_VIEWPORTS];
unsigned num_prescale;
unsigned num_rendertargets; unsigned num_rendertargets;
struct pipe_surface *rtv[SVGA3D_MAX_RENDER_TARGETS]; struct pipe_surface *rtv[SVGA3D_MAX_RENDER_TARGETS];
struct pipe_surface *dsv; struct pipe_surface *dsv;
@ -361,6 +386,9 @@ struct svga_hw_draw_state
struct svga_shader_variant *fs; struct svga_shader_variant *fs;
struct svga_shader_variant *vs; struct svga_shader_variant *vs;
struct svga_shader_variant *gs; struct svga_shader_variant *gs;
struct svga_shader_variant *tcs;
struct svga_shader_variant *tes;
struct svga_shader_variant *cs;
/** Currently bound constant buffer, per shader stage */ /** Currently bound constant buffer, per shader stage */
struct pipe_resource *constbuf[PIPE_SHADER_TYPES]; struct pipe_resource *constbuf[PIPE_SHADER_TYPES];
@ -495,7 +523,7 @@ struct svga_context
struct util_bitmask *query_id_bm; struct util_bitmask *query_id_bm;
struct { struct {
unsigned dirty[SVGA_STATE_MAX]; uint64_t dirty[SVGA_STATE_MAX];
/** bitmasks of which const buffers are changed */ /** bitmasks of which const buffers are changed */
unsigned dirty_constbufs[PIPE_SHADER_TYPES]; unsigned dirty_constbufs[PIPE_SHADER_TYPES];
@ -508,7 +536,7 @@ struct svga_context
} state; } state;
struct svga_state curr; /* state from the gallium frontend */ struct svga_state curr; /* state from the gallium frontend */
unsigned dirty; /* statechanges since last update_state() */ uint64_t dirty; /* statechanges since last update_state() */
union { union {
struct { struct {
@ -518,6 +546,9 @@ struct svga_context
unsigned vs:1; unsigned vs:1;
unsigned fs:1; unsigned fs:1;
unsigned gs:1; unsigned gs:1;
unsigned tcs:1;
unsigned tes:1;
unsigned cs:1;
unsigned query:1; unsigned query:1;
} flags; } flags;
unsigned val; unsigned val;
@ -531,7 +562,10 @@ struct svga_context
struct util_bitmask *gb_query_alloc_mask; /**< gb query object allocation mask */ struct util_bitmask *gb_query_alloc_mask; /**< gb query object allocation mask */
struct svga_qmem_alloc_entry *gb_query_map[SVGA_QUERY_MAX]; struct svga_qmem_alloc_entry *gb_query_map[SVGA_QUERY_MAX];
/**< query mem block mapping */ /**< query mem block mapping */
struct svga_query *sq[SVGA_QUERY_MAX]; /**< queries currently in progress */ struct svga_query *sq[SVGA_QUERY_MAX+12]; /**< queries currently in progress */
/* The last 12 entries are for streamout
* queries for stream 0..3
*/
/** List of buffers with queued transfers */ /** List of buffers with queued transfers */
struct list_head dirty_buffers; struct list_head dirty_buffers;
@ -545,6 +579,7 @@ struct svga_context
uint64_t map_buffer_time; /**< SVGA_QUERY_MAP_BUFFER_TIME */ uint64_t map_buffer_time; /**< SVGA_QUERY_MAP_BUFFER_TIME */
uint64_t num_buffers_mapped; /**< SVGA_QUERY_NUM_BUFFERS_MAPPED */ uint64_t num_buffers_mapped; /**< SVGA_QUERY_NUM_BUFFERS_MAPPED */
uint64_t num_textures_mapped; /**< SVGA_QUERY_NUM_TEXTURES_MAPPED */ uint64_t num_textures_mapped; /**< SVGA_QUERY_NUM_TEXTURES_MAPPED */
uint64_t num_command_buffers; /**< SVGA_QUERY_NUM_COMMAND_BUFFERS */
uint64_t command_buffer_size; /**< SVGA_QUERY_COMMAND_BUFFER_SIZE */ uint64_t command_buffer_size; /**< SVGA_QUERY_COMMAND_BUFFER_SIZE */
uint64_t flush_time; /**< SVGA_QUERY_FLUSH_TIME */ uint64_t flush_time; /**< SVGA_QUERY_FLUSH_TIME */
uint64_t surface_write_flushes; /**< SVGA_QUERY_SURFACE_WRITE_FLUSHES */ uint64_t surface_write_flushes; /**< SVGA_QUERY_SURFACE_WRITE_FLUSHES */
@ -566,16 +601,28 @@ struct svga_context
uint64_t num_surface_views; /**< SVGA_QUERY_NUM_SURFACE_VIEWS */ uint64_t num_surface_views; /**< SVGA_QUERY_NUM_SURFACE_VIEWS */
uint64_t num_bytes_uploaded; /**< SVGA_QUERY_NUM_BYTES_UPLOADED */ uint64_t num_bytes_uploaded; /**< SVGA_QUERY_NUM_BYTES_UPLOADED */
uint64_t num_generate_mipmap; /**< SVGA_QUERY_NUM_GENERATE_MIPMAP */ uint64_t num_generate_mipmap; /**< SVGA_QUERY_NUM_GENERATE_MIPMAP */
uint64_t shader_mem_used; /**< SVGA_QUERY_SHADER_MEM_USED */
boolean uses_time; /**< os_time_get() calls needed? */ boolean uses_time; /**< os_time_get() calls needed? */
} hud; } hud;
/** The currently bound stream output targets */ /** The currently bound stream output targets */
boolean in_streamout; /* Set if streamout is active */
unsigned num_so_targets; unsigned num_so_targets;
struct svga_winsys_surface *so_surfaces[SVGA3D_DX_MAX_SOTARGETS]; struct svga_winsys_surface *so_surfaces[SVGA3D_DX_MAX_SOTARGETS];
struct pipe_stream_output_target *so_targets[SVGA3D_DX_MAX_SOTARGETS]; struct pipe_stream_output_target *so_targets[SVGA3D_DX_MAX_SOTARGETS];
struct svga_stream_output *current_so; struct svga_stream_output *current_so;
/**
* The following states are used in the workaround for auto draw with
* stream instancing.
*/
/* Last bound SO targets that can be used to get vertex count */
struct pipe_stream_output_target *vcount_so_targets[SVGA3D_DX_MAX_SOTARGETS];
unsigned vcount_buffer_stream; /* SO buffer to stream index mask */
struct pipe_query *so_queries[4]; /* SO stat queries for each stream */
/** A blend state with blending disabled, for falling back to when blending /** A blend state with blending disabled, for falling back to when blending
* is illegal (e.g. an integer texture is bound) * is illegal (e.g. an integer texture is bound)
*/ */
@ -601,41 +648,58 @@ struct svga_context
boolean render_condition; boolean render_condition;
boolean disable_rasterizer; /* Set if to disable rasterization */ boolean disable_rasterizer; /* Set if to disable rasterization */
struct {
struct svga_tcs_shader *passthrough_tcs;
struct svga_vertex_shader *vs;
struct svga_tes_shader *tes;
unsigned vertices_per_patch;
boolean passthrough;
} tcs;
}; };
/* A flag for each frontend state object: /* A flag for each frontend state object:
*/ */
#define SVGA_NEW_BLEND 0x1 #define SVGA_NEW_BLEND ((uint64_t) 0x1)
#define SVGA_NEW_DEPTH_STENCIL_ALPHA 0x2 #define SVGA_NEW_DEPTH_STENCIL_ALPHA ((uint64_t) 0x2)
#define SVGA_NEW_RAST 0x4 #define SVGA_NEW_RAST ((uint64_t) 0x4)
#define SVGA_NEW_SAMPLER 0x8 #define SVGA_NEW_SAMPLER ((uint64_t) 0x8)
#define SVGA_NEW_TEXTURE 0x10 #define SVGA_NEW_TEXTURE ((uint64_t) 0x10)
#define SVGA_NEW_VBUFFER 0x20 #define SVGA_NEW_VBUFFER ((uint64_t) 0x20)
#define SVGA_NEW_VELEMENT 0x40 #define SVGA_NEW_VELEMENT ((uint64_t) 0x40)
#define SVGA_NEW_FS 0x80 #define SVGA_NEW_FS ((uint64_t) 0x80)
#define SVGA_NEW_VS 0x100 #define SVGA_NEW_VS ((uint64_t) 0x100)
#define SVGA_NEW_FS_CONST_BUFFER 0x200 #define SVGA_NEW_FS_CONST_BUFFER ((uint64_t) 0x200)
#define SVGA_NEW_VS_CONST_BUFFER 0x400 #define SVGA_NEW_VS_CONST_BUFFER ((uint64_t) 0x400)
#define SVGA_NEW_FRAME_BUFFER 0x800 #define SVGA_NEW_FRAME_BUFFER ((uint64_t) 0x800)
#define SVGA_NEW_STIPPLE 0x1000 #define SVGA_NEW_STIPPLE ((uint64_t) 0x1000)
#define SVGA_NEW_SCISSOR 0x2000 #define SVGA_NEW_SCISSOR ((uint64_t) 0x2000)
#define SVGA_NEW_BLEND_COLOR 0x4000 #define SVGA_NEW_BLEND_COLOR ((uint64_t) 0x4000)
#define SVGA_NEW_CLIP 0x8000 #define SVGA_NEW_CLIP ((uint64_t) 0x8000)
#define SVGA_NEW_VIEWPORT 0x10000 #define SVGA_NEW_VIEWPORT ((uint64_t) 0x10000)
#define SVGA_NEW_PRESCALE 0x20000 #define SVGA_NEW_PRESCALE ((uint64_t) 0x20000)
#define SVGA_NEW_REDUCED_PRIMITIVE 0x40000 #define SVGA_NEW_REDUCED_PRIMITIVE ((uint64_t) 0x40000)
#define SVGA_NEW_TEXTURE_BINDING 0x80000 #define SVGA_NEW_TEXTURE_BINDING ((uint64_t) 0x80000)
#define SVGA_NEW_NEED_PIPELINE 0x100000 #define SVGA_NEW_NEED_PIPELINE ((uint64_t) 0x100000)
#define SVGA_NEW_NEED_SWVFETCH 0x200000 #define SVGA_NEW_NEED_SWVFETCH ((uint64_t) 0x200000)
#define SVGA_NEW_NEED_SWTNL 0x400000 #define SVGA_NEW_NEED_SWTNL ((uint64_t) 0x400000)
#define SVGA_NEW_FS_VARIANT 0x800000 #define SVGA_NEW_FS_VARIANT ((uint64_t) 0x800000)
#define SVGA_NEW_VS_VARIANT 0x1000000 #define SVGA_NEW_VS_VARIANT ((uint64_t) 0x1000000)
#define SVGA_NEW_TEXTURE_FLAGS 0x4000000 #define SVGA_NEW_TEXTURE_FLAGS ((uint64_t) 0x4000000)
#define SVGA_NEW_STENCIL_REF 0x8000000 #define SVGA_NEW_STENCIL_REF ((uint64_t) 0x8000000)
#define SVGA_NEW_GS 0x10000000 #define SVGA_NEW_GS ((uint64_t) 0x10000000)
#define SVGA_NEW_GS_CONST_BUFFER 0x20000000 #define SVGA_NEW_GS_CONST_BUFFER ((uint64_t) 0x20000000)
#define SVGA_NEW_GS_VARIANT 0x40000000 #define SVGA_NEW_GS_VARIANT ((uint64_t) 0x40000000)
#define SVGA_NEW_TEXTURE_CONSTS 0x80000000 #define SVGA_NEW_TEXTURE_CONSTS ((uint64_t) 0x80000000)
#define SVGA_NEW_TCS ((uint64_t) 0x100000000)
#define SVGA_NEW_TES ((uint64_t) 0x200000000)
#define SVGA_NEW_TCS_VARIANT ((uint64_t) 0x400000000)
#define SVGA_NEW_TES_VARIANT ((uint64_t) 0x800000000)
#define SVGA_NEW_TCS_CONST_BUFFER ((uint64_t) 0x1000000000)
#define SVGA_NEW_TES_CONST_BUFFER ((uint64_t) 0x2000000000)
#define SVGA_NEW_TCS_PARAM ((uint64_t) 0x4000000000)
#define SVGA_NEW_ALL ((uint64_t) 0xFFFFFFFFFFFFFFFF)
void svga_init_state_functions( struct svga_context *svga ); void svga_init_state_functions( struct svga_context *svga );
@ -648,9 +712,11 @@ void svga_init_depth_stencil_functions( struct svga_context *svga );
void svga_init_misc_functions( struct svga_context *svga ); void svga_init_misc_functions( struct svga_context *svga );
void svga_init_rasterizer_functions( struct svga_context *svga ); void svga_init_rasterizer_functions( struct svga_context *svga );
void svga_init_sampler_functions( struct svga_context *svga ); void svga_init_sampler_functions( struct svga_context *svga );
void svga_init_cs_functions( struct svga_context *svga );
void svga_init_fs_functions( struct svga_context *svga ); void svga_init_fs_functions( struct svga_context *svga );
void svga_init_vs_functions( struct svga_context *svga ); void svga_init_vs_functions( struct svga_context *svga );
void svga_init_gs_functions( struct svga_context *svga ); void svga_init_gs_functions( struct svga_context *svga );
void svga_init_ts_functions( struct svga_context *svga );
void svga_init_vertex_functions( struct svga_context *svga ); void svga_init_vertex_functions( struct svga_context *svga );
void svga_init_constbuffer_functions( struct svga_context *svga ); void svga_init_constbuffer_functions( struct svga_context *svga );
void svga_init_draw_functions( struct svga_context *svga ); void svga_init_draw_functions( struct svga_context *svga );
@ -663,6 +729,7 @@ void svga_cleanup_vertex_state( struct svga_context *svga );
void svga_cleanup_sampler_state( struct svga_context *svga ); void svga_cleanup_sampler_state( struct svga_context *svga );
void svga_cleanup_tss_binding( struct svga_context *svga ); void svga_cleanup_tss_binding( struct svga_context *svga );
void svga_cleanup_framebuffer( struct svga_context *svga ); void svga_cleanup_framebuffer( struct svga_context *svga );
void svga_cleanup_tcs_state( struct svga_context *svga );
void svga_context_flush( struct svga_context *svga, void svga_context_flush( struct svga_context *svga,
struct pipe_fence_handle **pfence ); struct pipe_fence_handle **pfence );
@ -723,6 +790,12 @@ svga_have_sm4_1(const struct svga_context *svga)
return svga_screen(svga->pipe.screen)->sws->have_sm4_1; return svga_screen(svga->pipe.screen)->sws->have_sm4_1;
} }
static inline boolean
svga_have_sm5(const struct svga_context *svga)
{
return svga_screen(svga->pipe.screen)->sws->have_sm5;
}
static inline boolean static inline boolean
svga_need_to_rebind_resources(const struct svga_context *svga) svga_need_to_rebind_resources(const struct svga_context *svga)
{ {
@ -745,5 +818,107 @@ svga_get_time(struct svga_context *svga)
return svga->hud.uses_time ? os_time_get() : 0; return svga->hud.uses_time ? os_time_get() : 0;
} }
/*
* The SVGA_TRY_XX family of macros can be used to optionally replace a
* function call with an error value, the purpose is to trigger and test
* retry path handling.
*/
#ifdef DEBUG
/*
* Optionally replace a function call with a PIPE_ERROR_OUT_OF_MEMORY
* return value
*/
#define SVGA_TRY(_func) \
((SVGA_DEBUG & DEBUG_RETRY) ? PIPE_ERROR_OUT_OF_MEMORY : (_func))
/* Optionally replace a function call with a NULL return value */
#define SVGA_TRY_PTR(_func) \
((SVGA_DEBUG & DEBUG_RETRY) ? NULL : (_func))
/*
* Optionally replace a function call with a NULL return value, and set
* the _retry parameter to TRUE.
*/
#define SVGA_TRY_MAP(_func, _retry) \
((SVGA_DEBUG & DEBUG_RETRY) ? (_retry) = TRUE, NULL : (_func))
#else
#define SVGA_TRY(_func) (_func)
#define SVGA_TRY_PTR(_func) (_func)
#define SVGA_TRY_MAP(_func, _retry) (_func)
#endif
/**
* Enter retry processing after hitting out-of-command space
*/
static inline void
svga_retry_enter(struct svga_context *svga)
{
/* We shouldn't nest retries, but currently we do. */
if ((SVGA_DEBUG & DEBUG_RETRY) && svga->swc->in_retry) {
debug_printf("WARNING: Recursive retry. Level: %u.\n",
svga->swc->in_retry);
}
svga->swc->in_retry++;
}
/**
* Exit retry processing after hitting out-of-command space
*/
static inline void
svga_retry_exit(struct svga_context *svga)
{
assert(svga->swc->in_retry > 0);
svga->swc->in_retry--;
}
/**
* Perform a function call, and on failure flush the context and retry,
* asserting that the retry succeeded. On return, the boolean argument
* _retried indicates whether the function call was retried or not.
*/
#define SVGA_RETRY_CHECK(_svga, _func, _retried) \
do { \
enum pipe_error ret; \
\
ret = SVGA_TRY(_func); \
(_retried) = (ret != PIPE_OK); \
if (_retried) { \
svga_retry_enter(_svga); \
svga_context_flush(_svga, NULL); \
ret = (_func); \
assert(ret == PIPE_OK); \
svga_retry_exit(_svga); \
} \
} while(0)
/**
* Perform a function call, and on failure flush the context and retry,
* asserting that the retry succeeded.
*/
#define SVGA_RETRY(_svga, _func) \
do { \
UNUSED boolean retried; \
\
SVGA_RETRY_CHECK(_svga, _func, retried); \
} while(0)
/**
* Perform a function call, and on out-of-memory, flush the context and
* retry. The retry return value is stored in _ret for reuse.
*/
#define SVGA_RETRY_OOM(_svga, _ret, _func) \
do { \
(_ret) = SVGA_TRY(_func); \
if ((_ret) == PIPE_ERROR_OUT_OF_MEMORY) { \
svga_retry_enter(_svga); \
svga_context_flush(_svga, NULL); \
(_ret) = (_func); \
svga_retry_exit(_svga); \
} \
} while (0);
#endif #endif

View File

@ -46,6 +46,7 @@
#define DEBUG_CACHE 0x8000 #define DEBUG_CACHE 0x8000
#define DEBUG_STREAMOUT 0x10000 #define DEBUG_STREAMOUT 0x10000
#define DEBUG_SAMPLERS 0x20000 #define DEBUG_SAMPLERS 0x20000
#define DEBUG_RETRY 0x100000
#ifdef DEBUG #ifdef DEBUG
extern int SVGA_DEBUG; extern int SVGA_DEBUG;

View File

@ -349,7 +349,7 @@ validate_sampler_resources(struct svga_context *svga)
assert(svga_have_vgpu10(svga)); assert(svga_have_vgpu10(svga));
for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_COMPUTE; shader++) {
unsigned count = svga->curr.num_sampler_views[shader]; unsigned count = svga->curr.num_sampler_views[shader];
unsigned i; unsigned i;
struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS]; struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
@ -379,7 +379,8 @@ validate_sampler_resources(struct svga_context *svga)
if (shader == PIPE_SHADER_FRAGMENT && if (shader == PIPE_SHADER_FRAGMENT &&
svga->curr.rast->templ.poly_stipple_enable) { svga->curr.rast->templ.poly_stipple_enable) {
const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit; const unsigned unit =
svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
struct svga_pipe_sampler_view *sv = struct svga_pipe_sampler_view *sv =
svga->polygon_stipple.sampler_view; svga->polygon_stipple.sampler_view;
@ -415,7 +416,7 @@ validate_constant_buffers(struct svga_context *svga)
assert(svga_have_vgpu10(svga)); assert(svga_have_vgpu10(svga));
for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_COMPUTE; shader++) {
enum pipe_error ret; enum pipe_error ret;
struct svga_buffer *buffer; struct svga_buffer *buffer;
struct svga_winsys_surface *handle; struct svga_winsys_surface *handle;
@ -482,6 +483,8 @@ last_command_was_draw(const struct svga_context *svga)
case SVGA_3D_CMD_DX_DRAW_INSTANCED: case SVGA_3D_CMD_DX_DRAW_INSTANCED:
case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED: case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED:
case SVGA_3D_CMD_DX_DRAW_AUTO: case SVGA_3D_CMD_DX_DRAW_AUTO:
case SVGA_3D_CMD_DX_DRAW_INDEXED_INSTANCED_INDIRECT:
case SVGA_3D_CMD_DX_DRAW_INSTANCED_INDIRECT:
return true; return true;
default: default:
return false; return false;
@ -511,17 +514,51 @@ vertex_buffers_equal(unsigned count,
* Prepare the vertex buffers for a drawing command. * Prepare the vertex buffers for a drawing command.
*/ */
static enum pipe_error static enum pipe_error
validate_vertex_buffers(struct svga_hwtnl *hwtnl) validate_vertex_buffers(struct svga_hwtnl *hwtnl,
const struct pipe_stream_output_target *so_vertex_count)
{ {
struct svga_context *svga = hwtnl->svga; struct svga_context *svga = hwtnl->svga;
struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX]; struct pipe_resource *vbuffers[SVGA3D_INPUTREG_MAX];
struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX]; struct svga_winsys_surface *vbuffer_handles[SVGA3D_INPUTREG_MAX];
const unsigned vbuf_count = hwtnl->cmd.vbuf_count; struct svga_winsys_surface *so_vertex_count_handle;
const unsigned vbuf_count = so_vertex_count ? 1 : hwtnl->cmd.vbuf_count;
int last_vbuf = -1; int last_vbuf = -1;
unsigned i; unsigned i;
assert(svga_have_vgpu10(svga)); assert(svga_have_vgpu10(svga));
/* Get handle for each referenced vertex buffer, unless we're using a
* stream-out buffer to specify the drawing information (DrawAuto).
*/
if (so_vertex_count) {
i = 0;
}
else {
for (i = 0; i < vbuf_count; i++) {
struct svga_buffer *sbuf =
svga_buffer(hwtnl->cmd.vbufs[i].buffer.resource);
if (sbuf) {
vbuffer_handles[i] = svga_buffer_handle(svga, &sbuf->b.b,
PIPE_BIND_VERTEX_BUFFER);
assert(sbuf->key.flags & SVGA3D_SURFACE_BIND_VERTEX_BUFFER);
if (vbuffer_handles[i] == NULL)
return PIPE_ERROR_OUT_OF_MEMORY;
vbuffers[i] = &sbuf->b.b;
last_vbuf = i;
}
else {
vbuffers[i] = NULL;
vbuffer_handles[i] = NULL;
}
}
}
for (; i < svga->state.hw_draw.num_vbuffers; i++) {
vbuffers[i] = NULL;
vbuffer_handles[i] = NULL;
}
/* Get handle for each referenced vertex buffer */ /* Get handle for each referenced vertex buffer */
for (i = 0; i < vbuf_count; i++) { for (i = 0; i < vbuf_count; i++) {
struct svga_buffer *sbuf = struct svga_buffer *sbuf =
@ -558,15 +595,39 @@ validate_vertex_buffers(struct svga_hwtnl *hwtnl)
svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id; svga->state.hw_draw.layout_id = hwtnl->cmd.vdecl_layout_id;
} }
/* Get handle for the stream out buffer */
if (so_vertex_count) {
so_vertex_count_handle = svga_buffer_handle(svga,
so_vertex_count->buffer,
(PIPE_BIND_VERTEX_BUFFER |
PIPE_BIND_STREAM_OUTPUT));
if (!so_vertex_count_handle)
return PIPE_ERROR_OUT_OF_MEMORY;
}
else {
so_vertex_count_handle = NULL;
}
/* setup vertex buffers */ /* setup vertex buffers */
{ {
SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS]; SVGA3dVertexBuffer vbuffer_attrs[PIPE_MAX_ATTRIBS];
if (so_vertex_count) {
/* Set IA slot0 input buffer to the SO buffer */
assert(vbuf_count == 1);
vbuffer_attrs[0].stride = hwtnl->cmd.vbufs[0].stride;
vbuffer_attrs[0].offset = hwtnl->cmd.vbufs[0].buffer_offset;
vbuffer_attrs[0].sid = 0;
vbuffers[0] = so_vertex_count->buffer;
vbuffer_handles[0] = so_vertex_count_handle;
}
else {
for (i = 0; i < vbuf_count; i++) { for (i = 0; i < vbuf_count; i++) {
vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride; vbuffer_attrs[i].stride = hwtnl->cmd.vbufs[i].stride;
vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset; vbuffer_attrs[i].offset = hwtnl->cmd.vbufs[i].buffer_offset;
vbuffer_attrs[i].sid = 0; vbuffer_attrs[i].sid = 0;
} }
}
/* If any of the vertex buffer state has changed, issue /* If any of the vertex buffer state has changed, issue
* the SetVertexBuffers command. Otherwise, we will just * the SetVertexBuffers command. Otherwise, we will just
@ -736,10 +797,14 @@ static enum pipe_error
draw_vgpu10(struct svga_hwtnl *hwtnl, draw_vgpu10(struct svga_hwtnl *hwtnl,
const SVGA3dPrimitiveRange *range, const SVGA3dPrimitiveRange *range,
unsigned vcount, unsigned vcount,
unsigned min_index, unsigned max_index,
struct pipe_resource *ib, struct pipe_resource *ib,
unsigned start_instance, unsigned instance_count) unsigned start_instance, unsigned instance_count,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_stream_output_target *so_vertex_count)
{ {
struct svga_context *svga = hwtnl->svga; struct svga_context *svga = hwtnl->svga;
struct svga_winsys_surface *indirect_handle;
enum pipe_error ret; enum pipe_error ret;
assert(svga_have_vgpu10(svga)); assert(svga_have_vgpu10(svga));
@ -779,7 +844,7 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
if (ret != PIPE_OK) if (ret != PIPE_OK)
return ret; return ret;
ret = validate_vertex_buffers(hwtnl); ret = validate_vertex_buffers(hwtnl, so_vertex_count);
if (ret != PIPE_OK) if (ret != PIPE_OK)
return ret; return ret;
@ -789,6 +854,16 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
return ret; return ret;
} }
if (indirect) {
indirect_handle = svga_buffer_handle(svga, indirect->buffer,
PIPE_BIND_COMMAND_ARGS_BUFFER);
if (!indirect_handle)
return PIPE_ERROR_OUT_OF_MEMORY;
}
else {
indirect_handle = NULL;
}
/* Set primitive type (line, tri, etc) */ /* Set primitive type (line, tri, etc) */
if (svga->state.hw_draw.topology != range->primType) { if (svga->state.hw_draw.topology != range->primType) {
ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType); ret = SVGA3D_vgpu10_SetTopology(svga->swc, range->primType);
@ -800,15 +875,18 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
if (ib) { if (ib) {
/* indexed drawing */ /* indexed drawing */
if (instance_count > 1) { if (indirect) {
ret = SVGA3D_sm5_DrawIndexedInstancedIndirect(svga->swc,
indirect_handle,
indirect->offset);
}
else if (instance_count > 1) {
ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc, ret = SVGA3D_vgpu10_DrawIndexedInstanced(svga->swc,
vcount, vcount,
instance_count, instance_count,
0, /* startIndexLocation */ 0, /* startIndexLocation */
range->indexBias, range->indexBias,
start_instance); start_instance);
if (ret != PIPE_OK)
return ret;
} }
else { else {
/* non-instanced drawing */ /* non-instanced drawing */
@ -816,7 +894,8 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
vcount, vcount,
0, /* startIndexLocation */ 0, /* startIndexLocation */
range->indexBias); range->indexBias);
if (ret != PIPE_OK) }
if (ret != PIPE_OK) {
return ret; return ret;
} }
} }
@ -835,21 +914,29 @@ draw_vgpu10(struct svga_hwtnl *hwtnl,
assert(svga->state.hw_draw.ib == NULL); assert(svga->state.hw_draw.ib == NULL);
if (instance_count > 1) { if (so_vertex_count) {
/* Stream-output drawing */
ret = SVGA3D_vgpu10_DrawAuto(svga->swc);
}
else if (indirect) {
ret = SVGA3D_sm5_DrawInstancedIndirect(svga->swc,
indirect_handle,
indirect->offset);
}
else if (instance_count > 1) {
ret = SVGA3D_vgpu10_DrawInstanced(svga->swc, ret = SVGA3D_vgpu10_DrawInstanced(svga->swc,
vcount, vcount,
instance_count, instance_count,
range->indexBias, range->indexBias,
start_instance); start_instance);
if (ret != PIPE_OK)
return ret;
} }
else { else {
/* non-instanced */ /* non-instanced */
ret = SVGA3D_vgpu10_Draw(svga->swc, ret = SVGA3D_vgpu10_Draw(svga->swc,
vcount, vcount,
range->indexBias); range->indexBias);
if (ret != PIPE_OK) }
if (ret != PIPE_OK) {
return ret; return ret;
} }
} }
@ -1044,14 +1131,20 @@ check_draw_params(struct svga_hwtnl *hwtnl,
/** /**
* All drawing filters down into this function, either directly * All drawing filters down into this function, either directly
* on the hardware path or after doing software vertex processing. * on the hardware path or after doing software vertex processing.
* \param indirect if non-null, get the vertex count, first vertex, etc.
* from a buffer.
* \param so_vertex_count if non-null, get the vertex count from a
* stream-output target.
*/ */
enum pipe_error enum pipe_error
svga_hwtnl_prim(struct svga_hwtnl *hwtnl, svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
const SVGA3dPrimitiveRange *range, const SVGA3dPrimitiveRange *range,
unsigned vcount, unsigned vcount,
unsigned min_index, unsigned min_index, unsigned max_index,
unsigned max_index, struct pipe_resource *ib, struct pipe_resource *ib,
unsigned start_instance, unsigned instance_count) unsigned start_instance, unsigned instance_count,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_stream_output_target *so_vertex_count)
{ {
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
@ -1059,17 +1152,14 @@ svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
if (svga_have_vgpu10(hwtnl->svga)) { if (svga_have_vgpu10(hwtnl->svga)) {
/* draw immediately */ /* draw immediately */
ret = draw_vgpu10(hwtnl, range, vcount, ib, SVGA_RETRY(hwtnl->svga, draw_vgpu10(hwtnl, range, vcount, min_index,
start_instance, instance_count); max_index, ib, start_instance,
if (ret != PIPE_OK) { instance_count, indirect,
svga_context_flush(hwtnl->svga, NULL); so_vertex_count));
ret = draw_vgpu10(hwtnl, range, vcount, ib,
start_instance, instance_count);
assert(ret == PIPE_OK);
}
} }
else { else {
/* batch up drawing commands */ /* batch up drawing commands */
assert(indirect == NULL);
#ifdef DEBUG #ifdef DEBUG
check_draw_params(hwtnl, range, min_index, max_index, ib); check_draw_params(hwtnl, range, min_index, max_index, ib);
assert(start_instance == 0); assert(start_instance == 0);

View File

@ -60,7 +60,8 @@ svga_hwtnl_vertex_buffers(struct svga_hwtnl *hwtnl,
enum pipe_error enum pipe_error
svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl, svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
enum pipe_prim_type prim, unsigned start, unsigned count, enum pipe_prim_type prim, unsigned start, unsigned count,
unsigned start_instance, unsigned instance_count); unsigned start_instance, unsigned instance_count,
ubyte vertices_per_patch);
enum pipe_error enum pipe_error
svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl, svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,

View File

@ -175,13 +175,14 @@ done:
static enum pipe_error static enum pipe_error
simple_draw_arrays(struct svga_hwtnl *hwtnl, simple_draw_arrays(struct svga_hwtnl *hwtnl,
enum pipe_prim_type prim, unsigned start, unsigned count, enum pipe_prim_type prim, unsigned start, unsigned count,
unsigned start_instance, unsigned instance_count) unsigned start_instance, unsigned instance_count,
ubyte vertices_per_patch)
{ {
SVGA3dPrimitiveRange range; SVGA3dPrimitiveRange range;
unsigned hw_prim; unsigned hw_prim;
unsigned hw_count; unsigned hw_count;
hw_prim = svga_translate_prim(prim, count, &hw_count); hw_prim = svga_translate_prim(prim, count, &hw_count, vertices_per_patch);
if (hw_count == 0) if (hw_count == 0)
return PIPE_ERROR_BAD_INPUT; return PIPE_ERROR_BAD_INPUT;
@ -200,14 +201,16 @@ simple_draw_arrays(struct svga_hwtnl *hwtnl,
*/ */
return svga_hwtnl_prim(hwtnl, &range, count, return svga_hwtnl_prim(hwtnl, &range, count,
0, count - 1, NULL, 0, count - 1, NULL,
start_instance, instance_count); start_instance, instance_count,
NULL, NULL);
} }
enum pipe_error enum pipe_error
svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl, svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
enum pipe_prim_type prim, unsigned start, unsigned count, enum pipe_prim_type prim, unsigned start, unsigned count,
unsigned start_instance, unsigned instance_count) unsigned start_instance, unsigned instance_count,
ubyte vertices_per_patch)
{ {
enum pipe_prim_type gen_prim; enum pipe_prim_type gen_prim;
unsigned gen_size, gen_nr; unsigned gen_size, gen_nr;
@ -225,7 +228,7 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
} }
if (svga->curr.rast->templ.flatshade && if (svga->curr.rast->templ.flatshade &&
svga->state.hw_draw.fs->constant_color_output) { svga_fs_variant(svga->state.hw_draw.fs)->constant_color_output) {
/* The fragment color is a constant, not per-vertex so the whole /* The fragment color is a constant, not per-vertex so the whole
* primitive will be the same color (except for possible blending). * primitive will be the same color (except for possible blending).
* We can ignore the current provoking vertex state and use whatever * We can ignore the current provoking vertex state and use whatever
@ -273,7 +276,8 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
if (gen_type == U_GENERATE_LINEAR) { if (gen_type == U_GENERATE_LINEAR) {
ret = simple_draw_arrays(hwtnl, gen_prim, start, count, ret = simple_draw_arrays(hwtnl, gen_prim, start, count,
start_instance, instance_count); start_instance, instance_count,
vertices_per_patch);
} }
else { else {
struct pipe_resource *gen_buf = NULL; struct pipe_resource *gen_buf = NULL;
@ -299,7 +303,8 @@ svga_hwtnl_draw_arrays(struct svga_hwtnl *hwtnl,
count - 1, count - 1,
gen_prim, 0, gen_nr, gen_prim, 0, gen_nr,
start_instance, start_instance,
instance_count); instance_count,
vertices_per_patch);
} }
if (gen_buf) { if (gen_buf) {

View File

@ -186,14 +186,15 @@ svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
enum pipe_prim_type prim, unsigned start, enum pipe_prim_type prim, unsigned start,
unsigned count, unsigned count,
unsigned start_instance, unsigned start_instance,
unsigned instance_count) unsigned instance_count,
ubyte vertices_per_patch)
{ {
SVGA3dPrimitiveRange range; SVGA3dPrimitiveRange range;
unsigned hw_prim; unsigned hw_prim;
unsigned hw_count; unsigned hw_count;
unsigned index_offset = start * index_size; unsigned index_offset = start * index_size;
hw_prim = svga_translate_prim(prim, count, &hw_count); hw_prim = svga_translate_prim(prim, count, &hw_count, vertices_per_patch);
if (hw_count == 0) if (hw_count == 0)
return PIPE_OK; /* nothing to draw */ return PIPE_OK; /* nothing to draw */
@ -206,7 +207,8 @@ svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
return svga_hwtnl_prim(hwtnl, &range, count, return svga_hwtnl_prim(hwtnl, &range, count,
min_index, max_index, index_buffer, min_index, max_index, index_buffer,
start_instance, instance_count); start_instance, instance_count,
NULL, NULL);
} }
@ -234,12 +236,20 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
&gen_size, &gen_nr, &gen_func); &gen_size, &gen_nr, &gen_func);
} }
else { else {
unsigned hw_pv;
/* There is no geometry ordering with PATCH, so no need to
* consider provoking vertex mode for the translation.
* So use the same api_pv as the hw_pv.
*/
hw_pv = info->mode == PIPE_PRIM_PATCHES ? hwtnl->api_pv :
hwtnl->hw_pv;
gen_type = u_index_translator(svga_hw_prims, gen_type = u_index_translator(svga_hw_prims,
info->mode, info->mode,
info->index_size, info->index_size,
count, count,
hwtnl->api_pv, hwtnl->api_pv,
hwtnl->hw_pv, hw_pv,
PR_DISABLE, PR_DISABLE,
&gen_prim, &gen_size, &gen_nr, &gen_func); &gen_prim, &gen_size, &gen_nr, &gen_func);
} }
@ -271,7 +281,8 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
info->max_index, info->max_index,
gen_prim, index_offset, count, gen_prim, index_offset, count,
info->start_instance, info->start_instance,
info->instance_count); info->instance_count,
info->vertices_per_patch);
pipe_resource_reference(&index_buffer, NULL); pipe_resource_reference(&index_buffer, NULL);
} }
else { else {
@ -299,7 +310,8 @@ svga_hwtnl_draw_range_elements(struct svga_hwtnl *hwtnl,
gen_prim, gen_offset, gen_prim, gen_offset,
gen_nr, gen_nr,
info->start_instance, info->start_instance,
info->instance_count); info->instance_count,
info->vertices_per_patch);
} }
if (gen_buf) { if (gen_buf) {

View File

@ -52,7 +52,8 @@ static const unsigned svga_hw_prims =
(1 << PIPE_PRIM_LINES_ADJACENCY) | (1 << PIPE_PRIM_LINES_ADJACENCY) |
(1 << PIPE_PRIM_LINE_STRIP_ADJACENCY) | (1 << PIPE_PRIM_LINE_STRIP_ADJACENCY) |
(1 << PIPE_PRIM_TRIANGLES_ADJACENCY) | (1 << PIPE_PRIM_TRIANGLES_ADJACENCY) |
(1 << PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY)); (1 << PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) |
(1 << PIPE_PRIM_PATCHES));
/** /**
@ -64,7 +65,8 @@ static const unsigned svga_hw_prims =
* those to other types of primitives with index/translation code. * those to other types of primitives with index/translation code.
*/ */
static inline SVGA3dPrimitiveType static inline SVGA3dPrimitiveType
svga_translate_prim(unsigned mode, unsigned vcount, unsigned *prim_count) svga_translate_prim(unsigned mode, unsigned vcount, unsigned *prim_count,
ubyte vertices_per_patch)
{ {
switch (mode) { switch (mode) {
case PIPE_PRIM_POINTS: case PIPE_PRIM_POINTS:
@ -107,6 +109,13 @@ svga_translate_prim(unsigned mode, unsigned vcount, unsigned *prim_count)
*prim_count = vcount / 2 - 2 ; *prim_count = vcount / 2 - 2 ;
return SVGA3D_PRIMITIVE_TRIANGLESTRIP_ADJ; return SVGA3D_PRIMITIVE_TRIANGLESTRIP_ADJ;
case PIPE_PRIM_PATCHES:
*prim_count = vcount / vertices_per_patch ;
assert(vertices_per_patch >= 1);
assert(vertices_per_patch <= 32);
return (SVGA3D_PRIMITIVE_1_CONTROL_POINT_PATCH - 1)
+ vertices_per_patch;
default: default:
assert(0); assert(0);
*prim_count = 0; *prim_count = 0;
@ -218,7 +227,9 @@ svga_hwtnl_prim(struct svga_hwtnl *hwtnl,
unsigned min_index, unsigned min_index,
unsigned max_index, unsigned max_index,
struct pipe_resource *ib, struct pipe_resource *ib,
unsigned start_instance, unsigned instance_count); unsigned start_instance, unsigned instance_count,
const struct pipe_draw_indirect_info *indirect,
const struct pipe_stream_output_target *so_vertex_count);
enum pipe_error enum pipe_error
svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl, svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
@ -231,6 +242,7 @@ svga_hwtnl_simple_draw_range_elements(struct svga_hwtnl *hwtnl,
unsigned start, unsigned start,
unsigned count, unsigned count,
unsigned start_instance, unsigned start_instance,
unsigned instance_count); unsigned instance_count,
ubyte vertices_per_patch);
#endif #endif

View File

@ -176,11 +176,11 @@ static const struct vgpu10_format_entry format_conversion_table[] =
[ PIPE_FORMAT_R16G16B16A16_SINT ] = { SVGA3D_R16G16B16A16_SINT, SVGA3D_R16G16B16A16_SINT, SVGA3D_R16G16B16A16_SINT, 0 }, [ PIPE_FORMAT_R16G16B16A16_SINT ] = { SVGA3D_R16G16B16A16_SINT, SVGA3D_R16G16B16A16_SINT, SVGA3D_R16G16B16A16_SINT, 0 },
[ PIPE_FORMAT_R32_UINT ] = { SVGA3D_R32_UINT, SVGA3D_R32_UINT, SVGA3D_R32_UINT, 0 }, [ PIPE_FORMAT_R32_UINT ] = { SVGA3D_R32_UINT, SVGA3D_R32_UINT, SVGA3D_R32_UINT, 0 },
[ PIPE_FORMAT_R32G32_UINT ] = { SVGA3D_R32G32_UINT, SVGA3D_R32G32_UINT, SVGA3D_R32G32_UINT, 0 }, [ PIPE_FORMAT_R32G32_UINT ] = { SVGA3D_R32G32_UINT, SVGA3D_R32G32_UINT, SVGA3D_R32G32_UINT, 0 },
[ PIPE_FORMAT_R32G32B32_UINT ] = { SVGA3D_R32G32B32_UINT, SVGA3D_FORMAT_INVALID, SVGA3D_FORMAT_INVALID, 0 }, [ PIPE_FORMAT_R32G32B32_UINT ] = { SVGA3D_R32G32B32_UINT, SVGA3D_R32G32B32_UINT, SVGA3D_R32G32B32_UINT, 0 },
[ PIPE_FORMAT_R32G32B32A32_UINT ] = { SVGA3D_R32G32B32A32_UINT, SVGA3D_R32G32B32A32_UINT, SVGA3D_R32G32B32A32_UINT, 0 }, [ PIPE_FORMAT_R32G32B32A32_UINT ] = { SVGA3D_R32G32B32A32_UINT, SVGA3D_R32G32B32A32_UINT, SVGA3D_R32G32B32A32_UINT, 0 },
[ PIPE_FORMAT_R32_SINT ] = { SVGA3D_R32_SINT, SVGA3D_R32_SINT, SVGA3D_R32_SINT, 0 }, [ PIPE_FORMAT_R32_SINT ] = { SVGA3D_R32_SINT, SVGA3D_R32_SINT, SVGA3D_R32_SINT, 0 },
[ PIPE_FORMAT_R32G32_SINT ] = { SVGA3D_R32G32_SINT, SVGA3D_R32G32_SINT, SVGA3D_R32G32_SINT, 0 }, [ PIPE_FORMAT_R32G32_SINT ] = { SVGA3D_R32G32_SINT, SVGA3D_R32G32_SINT, SVGA3D_R32G32_SINT, 0 },
[ PIPE_FORMAT_R32G32B32_SINT ] = { SVGA3D_R32G32B32_SINT, SVGA3D_FORMAT_INVALID, SVGA3D_FORMAT_INVALID, 0 }, [ PIPE_FORMAT_R32G32B32_SINT ] = { SVGA3D_R32G32B32_SINT, SVGA3D_R32G32B32_SINT, SVGA3D_R32G32B32_SINT, 0 },
[ PIPE_FORMAT_R32G32B32A32_SINT ] = { SVGA3D_R32G32B32A32_SINT, SVGA3D_R32G32B32A32_SINT, SVGA3D_R32G32B32A32_SINT, 0 }, [ PIPE_FORMAT_R32G32B32A32_SINT ] = { SVGA3D_R32G32B32A32_SINT, SVGA3D_R32G32B32A32_SINT, SVGA3D_R32G32B32A32_SINT, 0 },
[ PIPE_FORMAT_A8_UINT ] = { SVGA3D_FORMAT_INVALID, SVGA3D_FORMAT_INVALID, SVGA3D_R8_UINT, TF_000X }, [ PIPE_FORMAT_A8_UINT ] = { SVGA3D_FORMAT_INVALID, SVGA3D_FORMAT_INVALID, SVGA3D_R8_UINT, TF_000X },
[ PIPE_FORMAT_I8_UINT ] = { SVGA3D_FORMAT_INVALID, SVGA3D_FORMAT_INVALID, SVGA3D_R8_UINT, TF_XXXX }, [ PIPE_FORMAT_I8_UINT ] = { SVGA3D_FORMAT_INVALID, SVGA3D_FORMAT_INVALID, SVGA3D_R8_UINT, TF_XXXX },
@ -2137,7 +2137,7 @@ svga_is_format_supported(struct pipe_screen *screen,
} }
if (util_format_is_srgb(format) && if (util_format_is_srgb(format) &&
(bindings & PIPE_BIND_DISPLAY_TARGET)) { (bindings & (PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET))) {
/* We only support sRGB rendering with vgpu10 */ /* We only support sRGB rendering with vgpu10 */
return false; return false;
} }
@ -2252,6 +2252,12 @@ svga_is_dx_format_supported(struct pipe_screen *screen,
return svga_format != SVGA3D_FORMAT_INVALID; return svga_format != SVGA3D_FORMAT_INVALID;
} }
if (bindings & PIPE_BIND_SAMPLER_VIEW && target == PIPE_BUFFER) {
unsigned flags;
svga_translate_texture_buffer_view_format(format, &svga_format, &flags);
return svga_format != SVGA3D_FORMAT_INVALID;
}
svga_format = svga_translate_format(ss, format, bindings); svga_format = svga_translate_format(ss, format, bindings);
if (svga_format == SVGA3D_FORMAT_INVALID) { if (svga_format == SVGA3D_FORMAT_INVALID) {
return false; return false;

View File

@ -87,6 +87,15 @@ svga_link_shaders(const struct tgsi_shader_info *outshader_info,
} }
} }
/* Find the index for position */
linkage->position_index = 0;
for (i = 0; i < outshader_info->num_outputs; i++) {
if (outshader_info->output_semantic_name[i] == TGSI_SEMANTIC_POSITION) {
linkage->position_index = i;
break;
}
}
linkage->num_inputs = inshader_info->num_inputs; linkage->num_inputs = inshader_info->num_inputs;
/* Things like the front-face register are handled here */ /* Things like the front-face register are handled here */
@ -100,7 +109,8 @@ svga_link_shaders(const struct tgsi_shader_info *outshader_info,
/* Debug */ /* Debug */
if (SVGA_DEBUG & DEBUG_TGSI) { if (SVGA_DEBUG & DEBUG_TGSI) {
unsigned reg = 0; uint64_t reg = 0;
uint64_t one = 1;
debug_printf("### linkage info: num_inputs=%d input_map_max=%d\n", debug_printf("### linkage info: num_inputs=%d input_map_max=%d\n",
linkage->num_inputs, linkage->input_map_max); linkage->num_inputs, linkage->input_map_max);
@ -116,10 +126,8 @@ svga_link_shaders(const struct tgsi_shader_info *outshader_info,
tgsi_interpolate_names[inshader_info->input_interpolate[i]]); tgsi_interpolate_names[inshader_info->input_interpolate[i]]);
/* make sure no repeating register index */ /* make sure no repeating register index */
if (reg & 1 << linkage->input_map[i]) { assert((reg & (one << linkage->input_map[i])) == 0);
assert(0); reg |= one << linkage->input_map[i];
}
reg |= 1 << linkage->input_map[i];
} }
} }
} }

View File

@ -9,6 +9,7 @@ struct svga_context;
struct shader_linkage struct shader_linkage
{ {
unsigned num_inputs; unsigned num_inputs;
unsigned position_index; /* position register index */
unsigned input_map_max; /* highest index of mapped inputs */ unsigned input_map_max; /* highest index of mapped inputs */
ubyte input_map[PIPE_MAX_SHADER_INPUTS]; ubyte input_map[PIPE_MAX_SHADER_INPUTS];
}; };

View File

@ -91,6 +91,51 @@ svga_translate_blend_func(unsigned mode)
} }
/**
* Translate gallium logicop mode to SVGA3D logicop mode.
*/
static int
translate_logicop(enum pipe_logicop op)
{
switch (op) {
case PIPE_LOGICOP_CLEAR:
return SVGA3D_DX11_LOGICOP_CLEAR;
case PIPE_LOGICOP_NOR:
return SVGA3D_DX11_LOGICOP_NOR;
case PIPE_LOGICOP_AND_INVERTED:
return SVGA3D_DX11_LOGICOP_AND_INVERTED;
case PIPE_LOGICOP_COPY_INVERTED:
return SVGA3D_DX11_LOGICOP_COPY_INVERTED;
case PIPE_LOGICOP_AND_REVERSE:
return SVGA3D_DX11_LOGICOP_AND_REVERSE;
case PIPE_LOGICOP_INVERT:
return SVGA3D_DX11_LOGICOP_INVERT;
case PIPE_LOGICOP_XOR:
return SVGA3D_DX11_LOGICOP_XOR;
case PIPE_LOGICOP_NAND:
return SVGA3D_DX11_LOGICOP_NAND;
case PIPE_LOGICOP_AND:
return SVGA3D_DX11_LOGICOP_AND;
case PIPE_LOGICOP_EQUIV:
return SVGA3D_DX11_LOGICOP_EQUIV;
case PIPE_LOGICOP_NOOP:
return SVGA3D_DX11_LOGICOP_NOOP;
case PIPE_LOGICOP_OR_INVERTED:
return SVGA3D_DX11_LOGICOP_OR_INVERTED;
case PIPE_LOGICOP_COPY:
return SVGA3D_DX11_LOGICOP_COPY;
case PIPE_LOGICOP_OR_REVERSE:
return SVGA3D_DX11_LOGICOP_OR_REVERSE;
case PIPE_LOGICOP_OR:
return SVGA3D_DX11_LOGICOP_OR;
case PIPE_LOGICOP_SET:
return SVGA3D_DX11_LOGICOP_SET;
default:
return SVGA3D_DX11_LOGICOP_COPY;
}
};
/** /**
* Define a vgpu10 blend state object for the given * Define a vgpu10 blend state object for the given
* svga blend state. * svga blend state.
@ -100,7 +145,6 @@ define_blend_state_object(struct svga_context *svga,
struct svga_blend_state *bs) struct svga_blend_state *bs)
{ {
SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS]; SVGA3dDXBlendStatePerRT perRT[SVGA3D_MAX_RENDER_TARGETS];
unsigned try;
int i; int i;
assert(svga_have_vgpu10(svga)); assert(svga_have_vgpu10(svga));
@ -116,31 +160,141 @@ define_blend_state_object(struct svga_context *svga,
perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha; perRT[i].destBlendAlpha = bs->rt[i].dstblend_alpha;
perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha; perRT[i].blendOpAlpha = bs->rt[i].blendeq_alpha;
perRT[i].renderTargetWriteMask = bs->rt[i].writemask; perRT[i].renderTargetWriteMask = bs->rt[i].writemask;
perRT[i].logicOpEnable = 0; perRT[i].logicOpEnable = bs->logicop_enabled;
perRT[i].logicOp = SVGA3D_LOGICOP_COPY; perRT[i].logicOp = bs->logicop_mode;
} }
/* Loop in case command buffer is full and we need to flush and retry */ SVGA_RETRY(svga, SVGA3D_vgpu10_DefineBlendState(svga->swc,
for (try = 0; try < 2; try++) {
enum pipe_error ret;
ret = SVGA3D_vgpu10_DefineBlendState(svga->swc,
bs->id, bs->id,
bs->alpha_to_coverage, bs->alpha_to_coverage,
bs->independent_blend_enable, bs->independent_blend_enable,
perRT); perRT));
if (ret == PIPE_OK) }
return;
svga_context_flush(svga, NULL);
/**
* If SVGA3D_DEVCAP_LOGIC_BLENDOPS is false, we can't directly implement
* GL's logicops. But we can emulate some of them. We set up the blending
* state for that here.
*/
static void
emulate_logicop(struct svga_context *svga,
unsigned logicop_func,
struct svga_blend_state *blend,
unsigned buffer)
{
switch (logicop_func) {
case PIPE_LOGICOP_XOR:
case PIPE_LOGICOP_INVERT:
blend->need_white_fragments = TRUE;
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ONE;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_SUBTRACT;
break;
case PIPE_LOGICOP_CLEAR:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ZERO;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_COPY:
blend->rt[buffer].blend_enable = FALSE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_COPY_INVERTED:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_NOOP:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ZERO;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_SET:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ONE;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_AND:
/* Approximate with minimum - works for the 0 & anything case: */
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_AND_REVERSE:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_AND_INVERTED:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_OR:
/* Approximate with maximum - works for the 1 | anything case: */
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_OR_REVERSE:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_OR_INVERTED:
blend->rt[buffer].blend_enable = TRUE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_NAND:
case PIPE_LOGICOP_NOR:
case PIPE_LOGICOP_EQUIV:
/* Fill these in with plausible values */
blend->rt[buffer].blend_enable = FALSE;
blend->rt[buffer].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[buffer].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[buffer].blendeq = SVGA3D_BLENDEQ_ADD;
break;
default:
assert(0);
break;
}
blend->rt[buffer].srcblend_alpha = blend->rt[buffer].srcblend;
blend->rt[buffer].dstblend_alpha = blend->rt[buffer].dstblend;
blend->rt[buffer].blendeq_alpha = blend->rt[buffer].blendeq;
if (logicop_func == PIPE_LOGICOP_XOR) {
pipe_debug_message(&svga->debug.callback, CONFORMANCE,
"XOR logicop mode has limited support");
}
else if (logicop_func != PIPE_LOGICOP_COPY) {
pipe_debug_message(&svga->debug.callback, CONFORMANCE,
"general logicops are not supported");
} }
} }
static void * static void *
svga_create_blend_state(struct pipe_context *pipe, svga_create_blend_state(struct pipe_context *pipe,
const struct pipe_blend_state *templ) const struct pipe_blend_state *templ)
{ {
struct svga_context *svga = svga_context(pipe); struct svga_context *svga = svga_context(pipe);
struct svga_screen *ss = svga_screen(pipe->screen);
struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state ); struct svga_blend_state *blend = CALLOC_STRUCT( svga_blend_state );
unsigned i; unsigned i;
@ -166,107 +320,18 @@ svga_create_blend_state(struct pipe_context *pipe,
* top of D3D9 API. Instead we try to simulate with various blend modes. * top of D3D9 API. Instead we try to simulate with various blend modes.
*/ */
if (templ->logicop_enable) { if (templ->logicop_enable) {
switch (templ->logicop_func) { if (ss->haveBlendLogicops) {
case PIPE_LOGICOP_XOR: blend->logicop_enabled = TRUE;
case PIPE_LOGICOP_INVERT: blend->logicop_mode = translate_logicop(templ->logicop_func);
blend->need_white_fragments = TRUE; blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
blend->rt[i].blend_enable = TRUE; blend->rt[i].blendeq_alpha = SVGA3D_BLENDEQ_ADD;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_SUBTRACT;
break;
case PIPE_LOGICOP_CLEAR:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO; blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO; blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM; blend->rt[i].srcblend_alpha = SVGA3D_BLENDOP_ZERO;
break; blend->rt[i].dstblend_alpha = SVGA3D_BLENDOP_ZERO;
case PIPE_LOGICOP_COPY:
blend->rt[i].blend_enable = FALSE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_COPY_INVERTED:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_NOOP:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
break;
case PIPE_LOGICOP_SET:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_AND:
/* Approximate with minimum - works for the 0 & anything case: */
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_AND_REVERSE:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_AND_INVERTED:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MINIMUM;
break;
case PIPE_LOGICOP_OR:
/* Approximate with maximum - works for the 1 | anything case: */
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_OR_REVERSE:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_SRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_INVDESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_OR_INVERTED:
blend->rt[i].blend_enable = TRUE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_INVSRCCOLOR;
blend->rt[i].dstblend = SVGA3D_BLENDOP_DESTCOLOR;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_MAXIMUM;
break;
case PIPE_LOGICOP_NAND:
case PIPE_LOGICOP_NOR:
case PIPE_LOGICOP_EQUIV:
/* Fill these in with plausible values */
blend->rt[i].blend_enable = FALSE;
blend->rt[i].srcblend = SVGA3D_BLENDOP_ONE;
blend->rt[i].dstblend = SVGA3D_BLENDOP_ZERO;
blend->rt[i].blendeq = SVGA3D_BLENDEQ_ADD;
break;
default:
assert(0);
break;
} }
blend->rt[i].srcblend_alpha = blend->rt[i].srcblend; else {
blend->rt[i].dstblend_alpha = blend->rt[i].dstblend; emulate_logicop(svga, templ->logicop_func, blend, i);
blend->rt[i].blendeq_alpha = blend->rt[i].blendeq;
if (templ->logicop_func == PIPE_LOGICOP_XOR) {
pipe_debug_message(&svga->debug.callback, CONFORMANCE,
"XOR logicop mode has limited support");
}
else if (templ->logicop_func != PIPE_LOGICOP_COPY) {
pipe_debug_message(&svga->debug.callback, CONFORMANCE,
"general logicops are not supported");
} }
} }
else { else {
@ -374,14 +439,7 @@ static void svga_delete_blend_state(struct pipe_context *pipe,
(struct svga_blend_state *) blend; (struct svga_blend_state *) blend;
if (svga_have_vgpu10(svga) && bs->id != SVGA3D_INVALID_ID) { if (svga_have_vgpu10(svga) && bs->id != SVGA3D_INVALID_ID) {
enum pipe_error ret; SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id));
ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
if (ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_DestroyBlendState(svga->swc, bs->id);
assert(ret == PIPE_OK);
}
if (bs->id == svga->state.hw_draw.blend_id) if (bs->id == svga->state.hw_draw.blend_id)
svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID; svga->state.hw_draw.blend_id = SVGA3D_INVALID_ID;

View File

@ -80,7 +80,6 @@ intra_surface_copy(struct svga_context *svga, struct pipe_resource *tex,
unsigned dst_x, unsigned dst_y, unsigned dst_z, unsigned dst_x, unsigned dst_y, unsigned dst_z,
unsigned width, unsigned height, unsigned depth) unsigned width, unsigned height, unsigned depth)
{ {
enum pipe_error ret;
SVGA3dCopyBox box; SVGA3dCopyBox box;
struct svga_texture *stex; struct svga_texture *stex;
@ -102,15 +101,8 @@ intra_surface_copy(struct svga_context *svga, struct pipe_resource *tex,
box.srcy = src_y; box.srcy = src_y;
box.srcz = src_z; box.srcz = src_z;
ret = SVGA3D_vgpu10_IntraSurfaceCopy(svga->swc, SVGA_RETRY(svga, SVGA3D_vgpu10_IntraSurfaceCopy(svga->swc, stex->handle,
stex->handle, level, layer_face, &box); level, layer_face, &box));
if (ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_IntraSurfaceCopy(svga->swc,
stex->handle, level, layer_face, &box);
assert(ret == PIPE_OK);
}
/* Mark the texture subresource as rendered-to. */ /* Mark the texture subresource as rendered-to. */
svga_set_texture_rendered_to(stex, layer_face, level); svga_set_texture_rendered_to(stex, layer_face, level);
} }
@ -630,11 +622,13 @@ try_blit(struct svga_context *svga, const struct pipe_blit_info *blit_info)
util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems); util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs); util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
util_blitter_save_geometry_shader(svga->blitter, svga->curr.user_gs); util_blitter_save_geometry_shader(svga->blitter, svga->curr.user_gs);
util_blitter_save_tessctrl_shader(svga->blitter, svga->curr.tcs);
util_blitter_save_tesseval_shader(svga->blitter, svga->curr.tes);
util_blitter_save_so_targets(svga->blitter, svga->num_so_targets, util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
(struct pipe_stream_output_target**)svga->so_targets); (struct pipe_stream_output_target**)svga->so_targets);
util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast); util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
util_blitter_save_viewport(svga->blitter, &svga->curr.viewport); util_blitter_save_viewport(svga->blitter, &svga->curr.viewport[0]);
util_blitter_save_scissor(svga->blitter, &svga->curr.scissor); util_blitter_save_scissor(svga->blitter, &svga->curr.scissor[0]);
util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs); util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend); util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
util_blitter_save_depth_stencil_alpha(svga->blitter, util_blitter_save_depth_stencil_alpha(svga->blitter,
@ -835,7 +829,6 @@ svga_resource_copy_region(struct pipe_context *pipe,
if (dst_tex->target == PIPE_BUFFER && src_tex->target == PIPE_BUFFER) { if (dst_tex->target == PIPE_BUFFER && src_tex->target == PIPE_BUFFER) {
/* can't copy within the same buffer, unfortunately */ /* can't copy within the same buffer, unfortunately */
if (svga_have_vgpu10(svga) && src_tex != dst_tex) { if (svga_have_vgpu10(svga) && src_tex != dst_tex) {
enum pipe_error ret;
struct svga_winsys_surface *src_surf; struct svga_winsys_surface *src_surf;
struct svga_winsys_surface *dst_surf; struct svga_winsys_surface *dst_surf;
struct svga_buffer *dbuffer = svga_buffer(dst_tex); struct svga_buffer *dbuffer = svga_buffer(dst_tex);
@ -844,15 +837,9 @@ svga_resource_copy_region(struct pipe_context *pipe,
src_surf = svga_buffer_handle(svga, src_tex, sbuffer->bind_flags); src_surf = svga_buffer_handle(svga, src_tex, sbuffer->bind_flags);
dst_surf = svga_buffer_handle(svga, dst_tex, dbuffer->bind_flags); dst_surf = svga_buffer_handle(svga, dst_tex, dbuffer->bind_flags);
ret = SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf, dst_surf, SVGA_RETRY(svga, SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf,
src_box->x, dstx, src_box->width); dst_surf, src_box->x, dstx,
if (ret != PIPE_OK) { src_box->width));
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_BufferCopy(svga->swc, src_surf, dst_surf,
src_box->x, dstx, src_box->width);
assert(ret == PIPE_OK);
}
dbuffer->dirty = TRUE; dbuffer->dirty = TRUE;
} }
else { else {

View File

@ -45,11 +45,13 @@ begin_blit(struct svga_context *svga)
util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems); util_blitter_save_vertex_elements(svga->blitter, (void*)svga->curr.velems);
util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs); util_blitter_save_vertex_shader(svga->blitter, svga->curr.vs);
util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs); util_blitter_save_geometry_shader(svga->blitter, svga->curr.gs);
util_blitter_save_tessctrl_shader(svga->blitter, svga->curr.tcs);
util_blitter_save_tesseval_shader(svga->blitter, svga->curr.tes);
util_blitter_save_so_targets(svga->blitter, svga->num_so_targets, util_blitter_save_so_targets(svga->blitter, svga->num_so_targets,
(struct pipe_stream_output_target**)svga->so_targets); (struct pipe_stream_output_target**)svga->so_targets);
util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast); util_blitter_save_rasterizer(svga->blitter, (void*)svga->curr.rast);
util_blitter_save_viewport(svga->blitter, &svga->curr.viewport); util_blitter_save_viewport(svga->blitter, &svga->curr.viewport[0]);
util_blitter_save_scissor(svga->blitter, &svga->curr.scissor); util_blitter_save_scissor(svga->blitter, &svga->curr.scissor[0]);
util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs); util_blitter_save_fragment_shader(svga->blitter, svga->curr.fs);
util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend); util_blitter_save_blend(svga->blitter, (void*)svga->curr.blend);
util_blitter_save_depth_stencil_alpha(svga->blitter, util_blitter_save_depth_stencil_alpha(svga->blitter,
@ -248,15 +250,7 @@ svga_clear(struct pipe_context *pipe, unsigned buffers, const struct pipe_scisso
/* flush any queued prims (don't want them to appear after the clear!) */ /* flush any queued prims (don't want them to appear after the clear!) */
svga_hwtnl_flush_retry(svga); svga_hwtnl_flush_retry(svga);
ret = try_clear( svga, buffers, color, depth, stencil ); SVGA_RETRY_OOM(svga, ret, try_clear( svga, buffers, color, depth, stencil));
if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
/* Flush command buffer and retry:
*/
svga_context_flush( svga, NULL );
ret = try_clear( svga, buffers, color, depth, stencil );
}
/* /*
* Mark target surfaces as dirty * Mark target surfaces as dirty
@ -277,7 +271,6 @@ svga_clear_texture(struct pipe_context *pipe,
{ {
struct svga_context *svga = svga_context(pipe); struct svga_context *svga = svga_context(pipe);
struct svga_surface *svga_surface_dst; struct svga_surface *svga_surface_dst;
enum pipe_error ret;
struct pipe_surface tmpl; struct pipe_surface tmpl;
struct pipe_surface *surface; struct pipe_surface *surface;
@ -309,8 +302,8 @@ svga_clear_texture(struct pipe_context *pipe,
stencil = 0; stencil = 0;
} }
else { else {
util_format_unpack_z_float(surface->format, &depth, data, 1); desc->unpack_z_float(&depth, 0, data, 0, 1, 1);
util_format_unpack_s_8uint(surface->format, &stencil, data, 1); desc->unpack_s_8uint(&stencil, 0, data, 0, 1, 1);
} }
if (util_format_has_depth(desc)) { if (util_format_has_depth(desc)) {
@ -334,17 +327,9 @@ svga_clear_texture(struct pipe_context *pipe,
/* clearing whole surface, use direct VGPU10 command */ /* clearing whole surface, use direct VGPU10 command */
ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, SVGA_RETRY(svga, SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv,
clear_flags, clear_flags,
stencil, depth); stencil, depth));
if (ret != PIPE_OK) {
/* flush and try again */
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv,
clear_flags,
stencil, depth);
assert(ret == PIPE_OK);
}
} }
else { else {
/* To clear subtexture use software fallback */ /* To clear subtexture use software fallback */
@ -367,7 +352,18 @@ svga_clear_texture(struct pipe_context *pipe,
color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0; color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0;
} }
else { else {
util_format_unpack_rgba(surface->format, color.ui, data, 1); if (util_format_is_pure_sint(surface->format)) {
/* signed integer */
desc->unpack_rgba_sint(color.i, 0, data, 0, 1, 1);
}
else if (util_format_is_pure_uint(surface->format)) {
/* unsigned integer */
desc->unpack_rgba_uint(color.ui, 0, data, 0, 1, 1);
}
else {
/* floating point */
desc->unpack_rgba_float(color.f, 0, data, 0, 1, 1);
}
} }
/* Setup render target view */ /* Setup render target view */
@ -390,14 +386,8 @@ svga_clear_texture(struct pipe_context *pipe,
} }
else { else {
/* clearing whole surface using VGPU10 command */ /* clearing whole surface using VGPU10 command */
ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, SVGA_RETRY(svga, SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv,
color.f); color.f));
if (ret != PIPE_OK) {
svga_context_flush(svga,NULL);
ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv,
color.f);
assert(ret == PIPE_OK);
}
} }
} }
else { else {
@ -527,12 +517,8 @@ svga_clear_render_target(struct pipe_context *pipe,
} else { } else {
enum pipe_error ret; enum pipe_error ret;
ret = svga_try_clear_render_target(svga, dst, color); SVGA_RETRY_OOM(svga, ret, svga_try_clear_render_target(svga, dst,
if (ret == PIPE_ERROR_OUT_OF_MEMORY) { color));
svga_context_flush( svga, NULL );
ret = svga_try_clear_render_target(svga, dst, color);
}
assert (ret == PIPE_OK); assert (ret == PIPE_OK);
} }
svga_toggle_render_condition(svga, render_condition_enabled, TRUE); svga_toggle_render_condition(svga, render_condition_enabled, TRUE);

View File

@ -24,12 +24,16 @@
**********************************************************/ **********************************************************/
#include "util/u_draw.h"
#include "util/format/u_format.h"
#include "util/u_helpers.h" #include "util/u_helpers.h"
#include "util/u_inlines.h" #include "util/u_inlines.h"
#include "util/u_prim.h" #include "util/u_prim.h"
#include "util/u_prim_restart.h" #include "util/u_prim_restart.h"
#include "svga_context.h" #include "svga_context.h"
#include "svga_draw_private.h"
#include "svga_screen.h"
#include "svga_draw.h" #include "svga_draw.h"
#include "svga_shader.h" #include "svga_shader.h"
#include "svga_surface.h" #include "svga_surface.h"
@ -37,59 +41,137 @@
#include "svga_debug.h" #include "svga_debug.h"
#include "svga_resource_buffer.h" #include "svga_resource_buffer.h"
/* Returns TRUE if we are currently using flat shading.
*/
static boolean
is_using_flat_shading(const struct svga_context *svga)
{
return
svga->state.hw_draw.fs ? svga->state.hw_draw.fs->uses_flat_interp : FALSE;
}
static enum pipe_error static enum pipe_error
retry_draw_range_elements(struct svga_context *svga, retry_draw_range_elements(struct svga_context *svga,
const struct pipe_draw_info *info, const struct pipe_draw_info *info,
unsigned count) unsigned count)
{ {
enum pipe_error ret;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWELEMENTS); SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWELEMENTS);
ret = svga_hwtnl_draw_range_elements(svga->hwtnl, info, count); SVGA_RETRY(svga, svga_hwtnl_draw_range_elements(svga->hwtnl, info, count));
if (ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = svga_hwtnl_draw_range_elements(svga->hwtnl, info, count);
}
assert (ret == PIPE_OK);
SVGA_STATS_TIME_POP(svga_sws(svga)); SVGA_STATS_TIME_POP(svga_sws(svga));
return ret; return PIPE_OK;
} }
static enum pipe_error static enum pipe_error
retry_draw_arrays( struct svga_context *svga, retry_draw_arrays( struct svga_context *svga,
enum pipe_prim_type prim, unsigned start, unsigned count, enum pipe_prim_type prim, unsigned start, unsigned count,
unsigned start_instance, unsigned instance_count) unsigned start_instance, unsigned instance_count,
ubyte vertices_per_patch)
{ {
enum pipe_error ret; enum pipe_error ret;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWARRAYS); SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWARRAYS);
for (unsigned try = 0; try < 2; try++) { SVGA_RETRY_OOM(svga, ret, svga_hwtnl_draw_arrays(svga->hwtnl, prim, start,
ret = svga_hwtnl_draw_arrays(svga->hwtnl, prim, start, count, count, start_instance,
start_instance, instance_count); instance_count,
if (ret == PIPE_OK) vertices_per_patch));
break;
svga_context_flush(svga, NULL);
}
SVGA_STATS_TIME_POP(svga_sws(svga)); SVGA_STATS_TIME_POP(svga_sws(svga));
return ret; return ret;
} }
/**
* Auto draw (get vertex count from a transform feedback result).
*/
static enum pipe_error
retry_draw_auto(struct svga_context *svga,
const struct pipe_draw_info *info)
{
assert(svga_have_sm5(svga));
assert(info->count_from_stream_output);
assert(info->instance_count == 1);
/* SO drawing implies core profile and none of these prim types */
assert(info->mode != PIPE_PRIM_QUADS &&
info->mode != PIPE_PRIM_QUAD_STRIP &&
info->mode != PIPE_PRIM_POLYGON);
if (info->mode == PIPE_PRIM_LINE_LOOP) {
/* XXX need to do a fallback */
assert(!"draw auto fallback not supported yet");
return PIPE_OK;
}
else {
SVGA3dPrimitiveRange range;
unsigned hw_count;
range.primType = svga_translate_prim(info->mode, 12, &hw_count,
info->vertices_per_patch);
range.primitiveCount = 0;
range.indexArray.surfaceId = SVGA3D_INVALID_ID;
range.indexArray.offset = 0;
range.indexArray.stride = 0;
range.indexWidth = 0;
range.indexBias = 0;
SVGA_RETRY(svga, svga_hwtnl_prim
(svga->hwtnl, &range,
0, /* vertex count comes from SO buffer */
0, /* don't know min index */
~0u, /* don't know max index */
NULL, /* no index buffer */
0, /* start instance */
1, /* only 1 instance supported */
NULL, /* indirect drawing info */
info->count_from_stream_output));
return PIPE_OK;
}
}
/**
* Indirect draw (get vertex count, start index, etc. from a buffer object.
*/
static enum pipe_error
retry_draw_indirect(struct svga_context *svga,
const struct pipe_draw_info *info)
{
assert(svga_have_sm5(svga));
assert(info->indirect);
/* indirect drawing implies core profile and none of these prim types */
assert(info->mode != PIPE_PRIM_QUADS &&
info->mode != PIPE_PRIM_QUAD_STRIP &&
info->mode != PIPE_PRIM_POLYGON);
if (info->mode == PIPE_PRIM_LINE_LOOP) {
/* need to do a fallback */
util_draw_indirect(&svga->pipe, info);
return PIPE_OK;
}
else {
SVGA3dPrimitiveRange range;
unsigned hw_count;
range.primType = svga_translate_prim(info->mode, 12, &hw_count,
info->vertices_per_patch);
range.primitiveCount = 0; /* specified in indirect buffer */
range.indexArray.surfaceId = SVGA3D_INVALID_ID;
range.indexArray.offset = 0;
range.indexArray.stride = 0;
range.indexWidth = info->index_size;
range.indexBias = 0; /* specified in indirect buffer */
SVGA_RETRY(svga, svga_hwtnl_prim
(svga->hwtnl, &range,
0, /* vertex count is in indirect buffer */
0, /* don't know min index */
~0u, /* don't know max index */
info->index.resource,
info->start_instance,
0, /* don't know instance count */
info->indirect,
NULL)); /* SO vertex count */
return PIPE_OK;
}
}
/** /**
* Determine if we need to implement primitive restart with a fallback * Determine if we need to implement primitive restart with a fallback
* path which breaks the original primitive into sub-primitive at the * path which breaks the original primitive into sub-primitive at the
@ -116,6 +198,21 @@ need_fallback_prim_restart(const struct svga_context *svga,
} }
/**
* A helper function to return the vertex count from the primitive count
* returned from the stream output statistics query for the specified stream.
*/
static unsigned
get_vcount_from_stream_output(struct svga_context *svga,
const struct pipe_draw_info *info,
unsigned stream)
{
unsigned primcount;
primcount = svga_get_primcount_from_stream_output(svga, stream);
return u_vertices_for_prims(info->mode, primcount);
}
static void static void
svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{ {
@ -147,6 +244,18 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE; svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
} }
if (svga->curr.vertices_per_patch != info->vertices_per_patch) {
svga->curr.vertices_per_patch = info->vertices_per_patch;
/* If input patch size changes, we need to notifiy the TCS
* code to reevaluate the shader variant since the
* vertices per patch count is a constant in the control
* point count declaration.
*/
if (svga->curr.tcs || svga->curr.tes)
svga->dirty |= SVGA_NEW_TCS_PARAM;
}
if (need_fallback_prim_restart(svga, info)) { if (need_fallback_prim_restart(svga, info)) {
enum pipe_error r; enum pipe_error r;
r = util_draw_vbo_without_prim_restart(pipe, info); r = util_draw_vbo_without_prim_restart(pipe, info);
@ -155,7 +264,8 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
goto done; goto done;
} }
if (!u_trim_pipe_prim(info->mode, &count)) if (!info->indirect && !info->count_from_stream_output &&
!u_trim_pipe_prim(info->mode, &count))
goto done; goto done;
needed_swtnl = svga->state.sw.need_swtnl; needed_swtnl = svga->state.sw.need_swtnl;
@ -189,20 +299,53 @@ svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
} }
svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode); svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
svga_update_state_retry(svga, SVGA_STATE_HW_DRAW);
/** determine if flatshade is to be used after svga_update_state() /** determine if flatshade is to be used after svga_update_state()
* in case the fragment shader is changed. * in case the fragment shader is changed.
*/ */
svga_hwtnl_set_flatshade(svga->hwtnl, svga_hwtnl_set_flatshade(svga->hwtnl,
svga->curr.rast->templ.flatshade || svga->curr.rast->templ.flatshade ||
is_using_flat_shading(svga), svga_is_using_flat_shading(svga),
svga->curr.rast->templ.flatshade_first); svga->curr.rast->templ.flatshade_first);
if (info->index_size) { if (info->count_from_stream_output) {
unsigned stream = 0;
assert(count == 0);
/* If the vertex count is from the stream output of a non-zero stream
* or the draw info specifies instancing, we will need a workaround
* since the draw_auto command does not support stream instancing.
* The workaround requires querying the vertex count from the
* stream output statistics query for the specified stream and then
* fallback to the regular draw function.
*/
/* Check the stream index of the specified stream output target */
for (unsigned i = 0; i < ARRAY_SIZE(svga->so_targets); i++) {
if (svga->vcount_so_targets[i] == info->count_from_stream_output) {
stream = (svga->vcount_buffer_stream >> (i * 4)) & 0xf;
break;
}
}
if (info->instance_count > 1 || stream > 0) {
count = get_vcount_from_stream_output(svga, info, stream);
}
}
if (info->count_from_stream_output && count == 0) {
ret = retry_draw_auto(svga, info);
}
else if (info->indirect) {
ret = retry_draw_indirect(svga, info);
}
else if (info->index_size) {
ret = retry_draw_range_elements(svga, info, count); ret = retry_draw_range_elements(svga, info, count);
} }
else { else {
ret = retry_draw_arrays(svga, info->mode, info->start, count, ret = retry_draw_arrays(svga, info->mode, info->start, count,
info->start_instance, info->instance_count); info->start_instance, info->instance_count,
info->vertices_per_patch);
} }
} }

View File

@ -37,7 +37,7 @@
#include "svga_shader.h" #include "svga_shader.h"
static void * void *
svga_create_fs_state(struct pipe_context *pipe, svga_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ) const struct pipe_shader_state *templ)
{ {
@ -69,7 +69,7 @@ svga_create_fs_state(struct pipe_context *pipe,
} }
static void void
svga_bind_fs_state(struct pipe_context *pipe, void *shader) svga_bind_fs_state(struct pipe_context *pipe, void *shader)
{ {
struct svga_fragment_shader *fs = (struct svga_fragment_shader *) shader; struct svga_fragment_shader *fs = (struct svga_fragment_shader *) shader;
@ -85,6 +85,7 @@ svga_delete_fs_state(struct pipe_context *pipe, void *shader)
{ {
struct svga_context *svga = svga_context(pipe); struct svga_context *svga = svga_context(pipe);
struct svga_fragment_shader *fs = (struct svga_fragment_shader *) shader; struct svga_fragment_shader *fs = (struct svga_fragment_shader *) shader;
struct svga_fragment_shader *next_fs;
struct svga_shader_variant *variant, *tmp; struct svga_shader_variant *variant, *tmp;
enum pipe_error ret; enum pipe_error ret;
@ -92,6 +93,9 @@ svga_delete_fs_state(struct pipe_context *pipe, void *shader)
assert(fs->base.parent == NULL); assert(fs->base.parent == NULL);
while (fs) {
next_fs = (struct svga_fragment_shader *) fs->base.next;
draw_delete_fragment_shader(svga->swtnl.draw, fs->draw_shader); draw_delete_fragment_shader(svga->swtnl.draw, fs->draw_shader);
for (variant = fs->base.variants; variant; variant = tmp) { for (variant = fs->base.variants; variant; variant = tmp) {
@ -113,6 +117,8 @@ svga_delete_fs_state(struct pipe_context *pipe, void *shader)
FREE((void *)fs->base.tokens); FREE((void *)fs->base.tokens);
FREE(fs); FREE(fs);
fs = next_fs;
}
} }

View File

@ -40,9 +40,16 @@ svga_set_scissor_states(struct pipe_context *pipe,
unsigned num_scissors, unsigned num_scissors,
const struct pipe_scissor_state *scissors) const struct pipe_scissor_state *scissors)
{ {
ASSERTED struct svga_screen *svgascreen = svga_screen(pipe->screen);
struct svga_context *svga = svga_context(pipe); struct svga_context *svga = svga_context(pipe);
unsigned i, num_sc;
assert(start_slot + num_scissors <= svgascreen->max_viewports);
for (i = 0, num_sc = start_slot; i < num_scissors; i++) {
svga->curr.scissor[num_sc++] = scissors[i]; /* struct copy */
}
memcpy(&svga->curr.scissor, scissors, sizeof(*scissors));
svga->dirty |= SVGA_NEW_SCISSOR; svga->dirty |= SVGA_NEW_SCISSOR;
} }
@ -199,8 +206,14 @@ svga_set_viewport_states(struct pipe_context *pipe,
const struct pipe_viewport_state *viewports) const struct pipe_viewport_state *viewports)
{ {
struct svga_context *svga = svga_context(pipe); struct svga_context *svga = svga_context(pipe);
ASSERTED struct svga_screen *svgascreen = svga_screen(pipe->screen);
unsigned i, num_vp;
svga->curr.viewport = *viewports; /* struct copy */ assert(start_slot + num_viewports <= svgascreen->max_viewports);
for (i = 0, num_vp = start_slot; i < num_viewports; i++) {
svga->curr.viewport[num_vp++] = viewports[i]; /* struct copy */
}
svga->dirty |= SVGA_NEW_VIEWPORT; svga->dirty |= SVGA_NEW_VIEWPORT;
} }

View File

@ -50,6 +50,7 @@ struct svga_query {
SVGA3dQueryType svga_type; /**< SVGA3D_QUERYTYPE_x or unused */ SVGA3dQueryType svga_type; /**< SVGA3D_QUERYTYPE_x or unused */
unsigned id; /** Per-context query identifier */ unsigned id; /** Per-context query identifier */
boolean active; /** TRUE if query is active */
struct pipe_fence_handle *fence; struct pipe_fence_handle *fence;
@ -214,10 +215,10 @@ get_query_result_vgpu9(struct svga_context *svga, struct svga_query *sq,
* will hold queries of the same type. Multiple memory blocks can be allocated * will hold queries of the same type. Multiple memory blocks can be allocated
* for a particular query type. * for a particular query type.
* *
* Currently each memory block is of 184 bytes. We support up to 128 * Currently each memory block is of 184 bytes. We support up to 512
* memory blocks. The query memory size is arbitrary right now. * memory blocks. The query memory size is arbitrary right now.
* Each occlusion query takes about 8 bytes. One memory block can accomodate * Each occlusion query takes about 8 bytes. One memory block can accomodate
* 23 occlusion queries. 128 of those blocks can support up to 2944 occlusion * 23 occlusion queries. 512 of those blocks can support up to 11K occlusion
* queries. That seems reasonable for now. If we think this limit is * queries. That seems reasonable for now. If we think this limit is
* not enough, we can increase the limit or try to grow the mob in runtime. * not enough, we can increase the limit or try to grow the mob in runtime.
* Note, SVGA device does not impose one mob per context for queries, * Note, SVGA device does not impose one mob per context for queries,
@ -228,7 +229,7 @@ get_query_result_vgpu9(struct svga_context *svga, struct svga_query *sq,
* following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery. * following commands: DXMoveQuery, DXBindAllQuery & DXReadbackAllQuery.
*/ */
#define SVGA_QUERY_MEM_BLOCK_SIZE (sizeof(SVGADXQueryResultUnion) * 2) #define SVGA_QUERY_MEM_BLOCK_SIZE (sizeof(SVGADXQueryResultUnion) * 2)
#define SVGA_QUERY_MEM_SIZE (128 * SVGA_QUERY_MEM_BLOCK_SIZE) #define SVGA_QUERY_MEM_SIZE (512 * SVGA_QUERY_MEM_BLOCK_SIZE)
struct svga_qmem_alloc_entry struct svga_qmem_alloc_entry
{ {
@ -243,31 +244,34 @@ struct svga_qmem_alloc_entry
/** /**
* Allocate a memory block from the query object memory * Allocate a memory block from the query object memory
* \return -1 if out of memory, else index of the query memory block * \return NULL if out of memory, else pointer to the query memory block
*/ */
static int static struct svga_qmem_alloc_entry *
allocate_query_block(struct svga_context *svga) allocate_query_block(struct svga_context *svga)
{ {
int index; int index;
unsigned offset; unsigned offset;
struct svga_qmem_alloc_entry *alloc_entry = NULL;
/* Find the next available query block */ /* Find the next available query block */
index = util_bitmask_add(svga->gb_query_alloc_mask); index = util_bitmask_add(svga->gb_query_alloc_mask);
if (index == UTIL_BITMASK_INVALID_INDEX) if (index == UTIL_BITMASK_INVALID_INDEX)
return -1; return NULL;
offset = index * SVGA_QUERY_MEM_BLOCK_SIZE; offset = index * SVGA_QUERY_MEM_BLOCK_SIZE;
if (offset >= svga->gb_query_len) { if (offset >= svga->gb_query_len) {
unsigned i; unsigned i;
/* Deallocate the out-of-range index */
util_bitmask_clear(svga->gb_query_alloc_mask, index);
index = -1;
/** /**
* All the memory blocks are allocated, lets see if there is * All the memory blocks are allocated, lets see if there is
* any empty memory block around that can be freed up. * any empty memory block around that can be freed up.
*/ */
index = -1;
for (i = 0; i < SVGA3D_QUERYTYPE_MAX && index == -1; i++) { for (i = 0; i < SVGA3D_QUERYTYPE_MAX && index == -1; i++) {
struct svga_qmem_alloc_entry *alloc_entry;
struct svga_qmem_alloc_entry *prev_alloc_entry = NULL; struct svga_qmem_alloc_entry *prev_alloc_entry = NULL;
alloc_entry = svga->gb_query_map[i]; alloc_entry = svga->gb_query_map[i];
@ -286,9 +290,20 @@ allocate_query_block(struct svga_context *svga)
} }
} }
} }
if (index == -1) {
debug_printf("Query memory object is full\n");
return NULL;
}
} }
return index; if (!alloc_entry) {
assert(index != -1);
alloc_entry = CALLOC_STRUCT(svga_qmem_alloc_entry);
alloc_entry->block_index = index;
}
return alloc_entry;
} }
/** /**
@ -346,17 +361,14 @@ allocate_query_block_entry(struct svga_context *svga,
unsigned len) unsigned len)
{ {
struct svga_qmem_alloc_entry *alloc_entry; struct svga_qmem_alloc_entry *alloc_entry;
int block_index = -1;
block_index = allocate_query_block(svga); alloc_entry = allocate_query_block(svga);
if (block_index == -1)
return NULL;
alloc_entry = CALLOC_STRUCT(svga_qmem_alloc_entry);
if (!alloc_entry) if (!alloc_entry)
return NULL; return NULL;
alloc_entry->block_index = block_index; assert(alloc_entry->block_index != -1);
alloc_entry->start_offset = block_index * SVGA_QUERY_MEM_BLOCK_SIZE; alloc_entry->start_offset =
alloc_entry->block_index * SVGA_QUERY_MEM_BLOCK_SIZE;
alloc_entry->nquery = 0; alloc_entry->nquery = 0;
alloc_entry->alloc_mask = util_bitmask_create(); alloc_entry->alloc_mask = util_bitmask_create();
alloc_entry->next = NULL; alloc_entry->next = NULL;
@ -508,17 +520,16 @@ define_query_vgpu10(struct svga_context *svga,
sq->gb_query = svga->gb_query; sq->gb_query = svga->gb_query;
/* Allocate an integer ID for this query */ /* Make sure query length is in multiples of 8 bytes */
sq->id = util_bitmask_add(svga->query_id_bm); qlen = align(resultLen + sizeof(SVGA3dQueryState), 8);
if (sq->id == UTIL_BITMASK_INVALID_INDEX)
return PIPE_ERROR_OUT_OF_MEMORY;
/* Find a slot for this query in the gb object */ /* Find a slot for this query in the gb object */
qlen = resultLen + sizeof(SVGA3dQueryState);
sq->offset = allocate_query(svga, sq->svga_type, qlen); sq->offset = allocate_query(svga, sq->svga_type, qlen);
if (sq->offset == -1) if (sq->offset == -1)
return PIPE_ERROR_OUT_OF_MEMORY; return PIPE_ERROR_OUT_OF_MEMORY;
assert((sq->offset & 7) == 0);
SVGA_DBG(DEBUG_QUERY, " query type=%d qid=0x%x offset=%d\n", SVGA_DBG(DEBUG_QUERY, " query type=%d qid=0x%x offset=%d\n",
sq->svga_type, sq->id, sq->offset); sq->svga_type, sq->id, sq->offset);
@ -731,7 +742,19 @@ svga_create_query(struct pipe_context *pipe,
case PIPE_QUERY_PRIMITIVES_EMITTED: case PIPE_QUERY_PRIMITIVES_EMITTED:
case PIPE_QUERY_SO_STATISTICS: case PIPE_QUERY_SO_STATISTICS:
assert(svga_have_vgpu10(svga)); assert(svga_have_vgpu10(svga));
/* Until the device supports the new query type for multiple streams,
* we will use the single stream query type for stream 0.
*/
if (svga_have_sm5(svga) && index > 0) {
assert(index < 4);
sq->svga_type = SVGA3D_QUERYTYPE_SOSTATS_STREAM0 + index;
}
else {
assert(index == 0);
sq->svga_type = SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS; sq->svga_type = SVGA3D_QUERYTYPE_STREAMOUTPUTSTATS;
}
ret = define_query_vgpu10(svga, sq, ret = define_query_vgpu10(svga, sq,
sizeof(SVGADXStreamOutStatisticsQueryResult)); sizeof(SVGADXStreamOutStatisticsQueryResult));
if (ret != PIPE_OK) if (ret != PIPE_OK)
@ -969,7 +992,10 @@ svga_begin_query(struct pipe_context *pipe, struct pipe_query *q)
assert(!"unexpected query type in svga_begin_query()"); assert(!"unexpected query type in svga_begin_query()");
} }
svga->sq[sq->type] = sq; SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d type=%d svga_type=%d\n",
__FUNCTION__, sq, sq->id, sq->type, sq->svga_type);
sq->active = TRUE;
return true; return true;
} }
@ -988,12 +1014,12 @@ svga_end_query(struct pipe_context *pipe, struct pipe_query *q)
SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__, SVGA_DBG(DEBUG_QUERY, "%s sq=0x%x id=%d\n", __FUNCTION__,
sq, sq->id); sq, sq->id);
if (sq->type == PIPE_QUERY_TIMESTAMP && svga->sq[sq->type] != sq) if (sq->type == PIPE_QUERY_TIMESTAMP && !sq->active)
svga_begin_query(pipe, q); svga_begin_query(pipe, q);
svga_hwtnl_flush_retry(svga); svga_hwtnl_flush_retry(svga);
assert(svga->sq[sq->type] == sq); assert(sq->active);
switch (sq->type) { switch (sq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER: case PIPE_QUERY_OCCLUSION_COUNTER:
@ -1083,7 +1109,7 @@ svga_end_query(struct pipe_context *pipe, struct pipe_query *q)
default: default:
assert(!"unexpected query type in svga_end_query()"); assert(!"unexpected query type in svga_end_query()");
} }
svga->sq[sq->type] = NULL; sq->active = FALSE;
return true; return true;
} }

View File

@ -118,6 +118,9 @@ define_rasterizer_object(struct svga_context *svga,
rast->templ.line_stipple_factor : 0; rast->templ.line_stipple_factor : 0;
const uint16 line_pattern = rast->templ.line_stipple_enable ? const uint16 line_pattern = rast->templ.line_stipple_enable ?
rast->templ.line_stipple_pattern : 0; rast->templ.line_stipple_pattern : 0;
const uint8 pv_last = !rast->templ.flatshade_first &&
svgascreen->haveProvokingVertex;
unsigned try; unsigned try;
rast->id = util_bitmask_add(svga->rast_object_id_bm); rast->id = util_bitmask_add(svga->rast_object_id_bm);
@ -194,7 +197,18 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
rast->templ.point_smooth = TRUE; rast->templ.point_smooth = TRUE;
} }
if (templ->point_smooth) { if (rast->templ.point_smooth &&
rast->templ.point_size_per_vertex == 0 &&
rast->templ.point_size <= screen->pointSmoothThreshold) {
/* If the point size is less than the threshold, disable smoothing.
* Note that this only effects point rendering when we use the
* pipe_rasterizer_state::point_size value, not when the point size
* is set in the VS.
*/
rast->templ.point_smooth = FALSE;
}
if (rast->templ.point_smooth) {
/* For smooth points we need to generate fragments for at least /* For smooth points we need to generate fragments for at least
* a 2x2 region. Otherwise the quad we draw may be too small and * a 2x2 region. Otherwise the quad we draw may be too small and
* we may generate no fragments at all. * we may generate no fragments at all.
@ -237,7 +251,7 @@ svga_create_rasterizer_state(struct pipe_context *pipe,
} }
} }
if (!svga_have_vgpu10(svga) && templ->point_smooth) { if (!svga_have_vgpu10(svga) && rast->templ.point_smooth) {
rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS; rast->need_pipeline |= SVGA_PIPELINE_FLAG_POINTS;
rast->need_pipeline_points_str = "smooth points"; rast->need_pipeline_points_str = "smooth points";
} }

View File

@ -44,6 +44,89 @@ svga_stream_output_target(struct pipe_stream_output_target *s)
return (struct svga_stream_output_target *)s; return (struct svga_stream_output_target *)s;
} }
/**
* A helper function to send different version of the DefineStreamOutput command
* depending on if device is SM5 capable or not.
*/
static enum pipe_error
svga_define_stream_output(struct svga_context *svga,
SVGA3dStreamOutputId soid,
uint32 numOutputStreamEntries,
uint32 numOutputStreamStrides,
uint32 streamStrides[SVGA3D_DX_MAX_SOTARGETS],
const SVGA3dStreamOutputDeclarationEntry decls[SVGA3D_MAX_STREAMOUT_DECLS],
uint32 rasterizedStream,
struct svga_stream_output *streamout)
{
unsigned i;
SVGA_DBG(DEBUG_STREAMOUT, "%s: id=%d\n", __FUNCTION__, soid);
SVGA_DBG(DEBUG_STREAMOUT,
"numOutputStreamEntires=%d\n", numOutputStreamEntries);
for (i = 0; i < numOutputStreamEntries; i++) {
SVGA_DBG(DEBUG_STREAMOUT,
" %d: slot=%d regIdx=%d regMask=0x%x stream=%d\n",
i, decls[i].outputSlot, decls[i].registerIndex,
decls[i].registerMask, decls[i].stream);
}
SVGA_DBG(DEBUG_STREAMOUT,
"numOutputStreamStrides=%d\n", numOutputStreamStrides);
for (i = 0; i < numOutputStreamStrides; i++) {
SVGA_DBG(DEBUG_STREAMOUT, " %d ", streamStrides[i]);
}
SVGA_DBG(DEBUG_STREAMOUT, "\n");
if (svga_have_sm5(svga) &&
(numOutputStreamEntries > SVGA3D_MAX_DX10_STREAMOUT_DECLS ||
numOutputStreamStrides > 1)) {
unsigned bufSize = sizeof(SVGA3dStreamOutputDeclarationEntry)
* numOutputStreamEntries;
struct svga_winsys_buffer *declBuf;
struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
void *map;
declBuf = svga_winsys_buffer_create(svga, 1, SVGA_BUFFER_USAGE_PINNED,
bufSize);
if (!declBuf)
return PIPE_ERROR;
map = sws->buffer_map(sws, declBuf, PIPE_TRANSFER_WRITE);
if (!map) {
sws->buffer_destroy(sws, declBuf);
return PIPE_ERROR;
}
/* copy decls to buffer */
memcpy(map, decls, bufSize);
/* unmap buffer */
sws->buffer_unmap(sws, declBuf);
streamout->declBuf = declBuf;
SVGA_RETRY(svga, SVGA3D_sm5_DefineAndBindStreamOutput
(svga->swc, soid,
numOutputStreamEntries,
numOutputStreamStrides,
streamStrides,
streamout->declBuf,
rasterizedStream,
bufSize));
} else {
SVGA_RETRY(svga, SVGA3D_vgpu10_DefineStreamOutput(svga->swc, soid,
numOutputStreamEntries,
streamStrides,
decls));
}
return PIPE_OK;
}
/**
* Creates stream output from the stream output info.
*/
struct svga_stream_output * struct svga_stream_output *
svga_create_stream_output(struct svga_context *svga, svga_create_stream_output(struct svga_context *svga,
struct svga_shader *shader, struct svga_shader *shader,
@ -52,9 +135,13 @@ svga_create_stream_output(struct svga_context *svga,
struct svga_stream_output *streamout; struct svga_stream_output *streamout;
SVGA3dStreamOutputDeclarationEntry decls[SVGA3D_MAX_STREAMOUT_DECLS]; SVGA3dStreamOutputDeclarationEntry decls[SVGA3D_MAX_STREAMOUT_DECLS];
unsigned strides[SVGA3D_DX_MAX_SOTARGETS]; unsigned strides[SVGA3D_DX_MAX_SOTARGETS];
unsigned dstOffset[SVGA3D_DX_MAX_SOTARGETS];
unsigned numStreamStrides = 0;
unsigned numDecls;
unsigned i; unsigned i;
enum pipe_error ret; enum pipe_error ret;
unsigned id; unsigned id;
ASSERTED unsigned maxDecls;
assert(info->num_outputs <= PIPE_MAX_SO_OUTPUTS); assert(info->num_outputs <= PIPE_MAX_SO_OUTPUTS);
@ -64,7 +151,12 @@ svga_create_stream_output(struct svga_context *svga,
if (!svga_have_vgpu10(svga)) if (!svga_have_vgpu10(svga))
return NULL; return NULL;
assert(info->num_outputs <= SVGA3D_MAX_STREAMOUT_DECLS); if (svga_have_sm5(svga))
maxDecls = SVGA3D_MAX_STREAMOUT_DECLS;
else if (svga_have_vgpu10(svga))
maxDecls = SVGA3D_MAX_DX10_STREAMOUT_DECLS;
assert(info->num_outputs <= maxDecls);
/* Allocate an integer ID for the stream output */ /* Allocate an integer ID for the stream output */
id = util_bitmask_add(svga->stream_output_id_bm); id = util_bitmask_add(svga->stream_output_id_bm);
@ -81,15 +173,17 @@ svga_create_stream_output(struct svga_context *svga,
streamout->info = *info; streamout->info = *info;
streamout->id = id; streamout->id = id;
streamout->pos_out_index = -1; streamout->pos_out_index = -1;
streamout->streammask = 0;
SVGA_DBG(DEBUG_STREAMOUT, "%s, num_outputs=%d id=%d\n", __FUNCTION__, /* Init whole decls and stride arrays to zero to avoid garbage values */
info->num_outputs, id);
/* init whole decls and stride arrays to zero to avoid garbage values */
memset(decls, 0, sizeof(decls)); memset(decls, 0, sizeof(decls));
memset(strides, 0, sizeof(strides)); memset(strides, 0, sizeof(strides));
memset(dstOffset, 0, sizeof(dstOffset));
for (i = 0; i < info->num_outputs; i++) { SVGA_DBG(DEBUG_STREAMOUT, "%s: num_outputs\n",
__FUNCTION__, info->num_outputs);
for (i = 0, numDecls = 0; i < info->num_outputs; i++, numDecls++) {
unsigned reg_idx = info->output[i].register_index; unsigned reg_idx = info->output[i].register_index;
unsigned buf_idx = info->output[i].output_buffer; unsigned buf_idx = info->output[i].output_buffer;
const enum tgsi_semantic sem_name = const enum tgsi_semantic sem_name =
@ -97,17 +191,59 @@ svga_create_stream_output(struct svga_context *svga,
assert(buf_idx <= PIPE_MAX_SO_BUFFERS); assert(buf_idx <= PIPE_MAX_SO_BUFFERS);
numStreamStrides = MAX2(numStreamStrides, buf_idx);
SVGA_DBG(DEBUG_STREAMOUT,
" %d: register_index=%d output_buffer=%d stream=%d\n",
i, reg_idx, buf_idx, info->output[i].stream);
SVGA_DBG(DEBUG_STREAMOUT,
" dst_offset=%d start_component=%d num_components=%d\n",
info->output[i].dst_offset,
info->output[i].start_component,
info->output[i].num_components);
streamout->buffer_stream |= info->output[i].stream << (buf_idx * 4);
/**
* Check if the destination offset of the current output
* is at the expected offset. If it is greater, then that means
* there is a gap in the stream output. We need to insert
* extra declaration entries with an invalid register index
* to specify a gap.
*/
while (info->output[i].dst_offset > dstOffset[buf_idx]) {
unsigned numComponents = info->output[i].dst_offset -
dstOffset[buf_idx];;
assert(svga_have_sm5(svga));
/* We can only specify at most 4 components to skip in each
* declaration entry.
*/
numComponents = numComponents > 4 ? 4 : numComponents;
decls[numDecls].outputSlot = buf_idx,
decls[numDecls].stream = info->output[i].stream;
decls[numDecls].registerIndex = SVGA3D_INVALID_ID;
decls[numDecls].registerMask = (1 << numComponents) - 1;
dstOffset[buf_idx] += numComponents;
numDecls++;
}
if (sem_name == TGSI_SEMANTIC_POSITION) { if (sem_name == TGSI_SEMANTIC_POSITION) {
/** /**
* Check if streaming out POSITION. If so, replace the * Check if streaming out POSITION. If so, replace the
* register index with the index for NON_ADJUSTED POSITION. * register index with the index for NON_ADJUSTED POSITION.
*/ */
decls[i].registerIndex = shader->info.num_outputs; decls[numDecls].registerIndex = shader->info.num_outputs;
/* Save this output index, so we can tell later if this stream output /* Save this output index, so we can tell later if this stream output
* includes an output of a vertex position * includes an output of a vertex position
*/ */
streamout->pos_out_index = i; streamout->pos_out_index = numDecls;
} }
else if (sem_name == TGSI_SEMANTIC_CLIPDIST) { else if (sem_name == TGSI_SEMANTIC_CLIPDIST) {
/** /**
@ -116,44 +252,49 @@ svga_create_stream_output(struct svga_context *svga,
* It's valid to write to ClipDistance variable for non-enabled * It's valid to write to ClipDistance variable for non-enabled
* clip planes. * clip planes.
*/ */
decls[i].registerIndex = shader->info.num_outputs + 1 + decls[numDecls].registerIndex =
shader->info.num_outputs + 1 +
shader->info.output_semantic_index[reg_idx]; shader->info.output_semantic_index[reg_idx];
} }
else { else {
decls[i].registerIndex = reg_idx; decls[numDecls].registerIndex = reg_idx;
} }
decls[i].outputSlot = buf_idx; decls[numDecls].outputSlot = buf_idx;
decls[i].registerMask = decls[numDecls].registerMask =
((1 << info->output[i].num_components) - 1) ((1 << info->output[i].num_components) - 1)
<< info->output[i].start_component; << info->output[i].start_component;
SVGA_DBG(DEBUG_STREAMOUT, "%d slot=%d regIdx=%d regMask=0x%x\n", decls[numDecls].stream = info->output[i].stream;
i, decls[i].outputSlot, decls[i].registerIndex, assert(decls[numDecls].stream == 0 || svga_have_sm5(svga));
decls[i].registerMask);
/* Set the bit in streammask for the enabled stream */
streamout->streammask |= 1 << info->output[i].stream;
/* Update the expected offset for the next output */
dstOffset[buf_idx] += info->output[i].num_components;
strides[buf_idx] = info->stride[buf_idx] * sizeof(float); strides[buf_idx] = info->stride[buf_idx] * sizeof(float);
} }
ret = SVGA3D_vgpu10_DefineStreamOutput(svga->swc, id, assert(numDecls <= maxDecls);
info->num_outputs,
strides, /* Send the DefineStreamOutput command.
decls); * Note, rasterizedStream is always 0.
if (ret != PIPE_OK) { */
svga_context_flush(svga, NULL); ret = svga_define_stream_output(svga, id,
ret = SVGA3D_vgpu10_DefineStreamOutput(svga->swc, id, numDecls, numStreamStrides+1,
info->num_outputs, strides, decls, 0, streamout);
strides,
decls);
if (ret != PIPE_OK) { if (ret != PIPE_OK) {
util_bitmask_clear(svga->stream_output_id_bm, id); util_bitmask_clear(svga->stream_output_id_bm, id);
FREE(streamout); FREE(streamout);
streamout = NULL; streamout = NULL;
} }
}
return streamout; return streamout;
} }
enum pipe_error enum pipe_error
svga_set_stream_output(struct svga_context *svga, svga_set_stream_output(struct svga_context *svga,
struct svga_stream_output *streamout) struct svga_stream_output *streamout)
@ -168,12 +309,28 @@ svga_set_stream_output(struct svga_context *svga,
streamout, id); streamout, id);
if (svga->current_so != streamout) { if (svga->current_so != streamout) {
/* Before unbinding the current stream output, stop the stream output
* statistics queries for the active streams.
*/
if (svga_have_sm5(svga) && svga->current_so) {
svga->vcount_buffer_stream = svga->current_so->buffer_stream;
svga_end_stream_output_queries(svga, svga->current_so->streammask);
}
enum pipe_error ret = SVGA3D_vgpu10_SetStreamOutput(svga->swc, id); enum pipe_error ret = SVGA3D_vgpu10_SetStreamOutput(svga->swc, id);
if (ret != PIPE_OK) { if (ret != PIPE_OK) {
return ret; return ret;
} }
svga->current_so = streamout; svga->current_so = streamout;
/* After binding the new stream output, start the stream output
* statistics queries for the active streams.
*/
if (svga_have_sm5(svga) && svga->current_so) {
svga_begin_stream_output_queries(svga, svga->current_so->streammask);
}
} }
return PIPE_OK; return PIPE_OK;
@ -183,17 +340,18 @@ void
svga_delete_stream_output(struct svga_context *svga, svga_delete_stream_output(struct svga_context *svga,
struct svga_stream_output *streamout) struct svga_stream_output *streamout)
{ {
enum pipe_error ret; struct svga_winsys_screen *sws = svga_screen(svga->pipe.screen)->sws;
SVGA_DBG(DEBUG_STREAMOUT, "%s streamout=0x%x\n", __FUNCTION__, streamout); SVGA_DBG(DEBUG_STREAMOUT, "%s streamout=0x%x\n", __FUNCTION__, streamout);
assert(svga_have_vgpu10(svga)); assert(svga_have_vgpu10(svga));
assert(streamout != NULL); assert(streamout != NULL);
ret = SVGA3D_vgpu10_DestroyStreamOutput(svga->swc, streamout->id); SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyStreamOutput(svga->swc,
if (ret != PIPE_OK) { streamout->id));
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_DestroyStreamOutput(svga->swc, streamout->id); if (svga_have_sm5(svga) && streamout->declBuf) {
sws->buffer_destroy(sws, streamout->declBuf);
} }
/* Release the ID */ /* Release the ID */
@ -203,6 +361,7 @@ svga_delete_stream_output(struct svga_context *svga,
FREE(streamout); FREE(streamout);
} }
static struct pipe_stream_output_target * static struct pipe_stream_output_target *
svga_create_stream_output_target(struct pipe_context *pipe, svga_create_stream_output_target(struct pipe_context *pipe,
struct pipe_resource *buffer, struct pipe_resource *buffer,
@ -252,9 +411,9 @@ svga_set_stream_output_targets(struct pipe_context *pipe,
{ {
struct svga_context *svga = svga_context(pipe); struct svga_context *svga = svga_context(pipe);
struct SVGA3dSoTarget soBindings[SVGA3D_DX_MAX_SOTARGETS]; struct SVGA3dSoTarget soBindings[SVGA3D_DX_MAX_SOTARGETS];
enum pipe_error ret;
unsigned i; unsigned i;
unsigned num_so_targets; unsigned num_so_targets;
boolean begin_so_queries = num_targets > 0;
SVGA_DBG(DEBUG_STREAMOUT, "%s num_targets=%d\n", __FUNCTION__, SVGA_DBG(DEBUG_STREAMOUT, "%s num_targets=%d\n", __FUNCTION__,
num_targets); num_targets);
@ -269,6 +428,14 @@ svga_set_stream_output_targets(struct pipe_context *pipe,
sbuf->dirty = TRUE; sbuf->dirty = TRUE;
} }
/* Before the currently bound streamout targets are unbound,
* save them in case they need to be referenced to retrieve the
* number of vertices being streamed out.
*/
for (i = 0; i < ARRAY_SIZE(svga->so_targets); i++) {
svga->vcount_so_targets[i] = svga->so_targets[i];
}
assert(num_targets <= SVGA3D_DX_MAX_SOTARGETS); assert(num_targets <= SVGA3D_DX_MAX_SOTARGETS);
for (i = 0; i < num_targets; i++) { for (i = 0; i < num_targets; i++) {
@ -283,7 +450,16 @@ svga_set_stream_output_targets(struct pipe_context *pipe,
& SVGA3D_SURFACE_BIND_STREAM_OUTPUT); & SVGA3D_SURFACE_BIND_STREAM_OUTPUT);
svga->so_targets[i] = &sot->base; svga->so_targets[i] = &sot->base;
soBindings[i].offset = sot->base.buffer_offset; if (offsets[i] == -1) {
soBindings[i].offset = -1;
/* The streamout is being resumed. There is no need to restart streamout statistics
* queries for the draw-auto fallback since those queries are still active.
*/
begin_so_queries = FALSE;
}
else
soBindings[i].offset = sot->base.buffer_offset + offsets[i];
/* The size cannot extend beyond the end of the buffer. Clamp it. */ /* The size cannot extend beyond the end of the buffer. Clamp it. */
size = MIN2(sot->base.buffer_size, size = MIN2(sot->base.buffer_size,
@ -299,15 +475,22 @@ svga_set_stream_output_targets(struct pipe_context *pipe,
} }
num_so_targets = MAX2(svga->num_so_targets, num_targets); num_so_targets = MAX2(svga->num_so_targets, num_targets);
ret = SVGA3D_vgpu10_SetSOTargets(svga->swc, num_so_targets, SVGA_RETRY(svga, SVGA3D_vgpu10_SetSOTargets(svga->swc, num_so_targets,
soBindings, svga->so_surfaces); soBindings, svga->so_surfaces));
if (ret != PIPE_OK) { svga->num_so_targets = num_targets;
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_SetSOTargets(svga->swc, num_so_targets, if (svga_have_sm5(svga) && svga->current_so && begin_so_queries) {
soBindings, svga->so_surfaces);
/* If there are aleady active queries and we need to start a new streamout,
* we need to stop the current active queries first.
*/
if (svga->in_streamout) {
svga_end_stream_output_queries(svga, svga->current_so->streammask);
} }
svga->num_so_targets = num_targets; /* Start stream out statistics queries for the new streamout */
svga_begin_stream_output_queries(svga, svga->current_so->streammask);
}
} }
/** /**
@ -329,6 +512,7 @@ svga_rebind_stream_output_targets(struct svga_context *svga)
return PIPE_OK; return PIPE_OK;
} }
void void
svga_init_stream_output_functions(struct svga_context *svga) svga_init_stream_output_functions(struct svga_context *svga)
{ {
@ -336,3 +520,117 @@ svga_init_stream_output_functions(struct svga_context *svga)
svga->pipe.stream_output_target_destroy = svga_destroy_stream_output_target; svga->pipe.stream_output_target_destroy = svga_destroy_stream_output_target;
svga->pipe.set_stream_output_targets = svga_set_stream_output_targets; svga->pipe.set_stream_output_targets = svga_set_stream_output_targets;
} }
/**
* A helper function to create stream output statistics queries for each stream.
* These queries are created as a workaround for DrawTransformFeedbackInstanced or
* DrawTransformFeedbackStreamInstanced when auto draw doesn't support
* instancing or non-0 stream. In this case, the vertex count will
* be retrieved from the stream output statistics query.
*/
void
svga_create_stream_output_queries(struct svga_context *svga)
{
unsigned i;
if (!svga_have_sm5(svga))
return;
for (i = 0; i < ARRAY_SIZE(svga->so_queries); i++) {
svga->so_queries[i] = svga->pipe.create_query(&svga->pipe,
PIPE_QUERY_SO_STATISTICS, i);
assert(svga->so_queries[i] != NULL);
}
}
/**
* Destroy the stream output statistics queries for the draw-auto workaround.
*/
void
svga_destroy_stream_output_queries(struct svga_context *svga)
{
unsigned i;
if (!svga_have_sm5(svga))
return;
for (i = 0; i < ARRAY_SIZE(svga->so_queries); i++) {
svga->pipe.destroy_query(&svga->pipe, svga->so_queries[i]);
}
}
/**
* Start stream output statistics queries for the active streams.
*/
void
svga_begin_stream_output_queries(struct svga_context *svga,
unsigned streammask)
{
assert(svga_have_sm5(svga));
assert(!svga->in_streamout);
for (unsigned i = 0; i < ARRAY_SIZE(svga->so_queries); i++) {
bool ret;
if (streammask & (1 << i)) {
ret = svga->pipe.begin_query(&svga->pipe, svga->so_queries[i]);
}
(void) ret;
}
svga->in_streamout = TRUE;
return;
}
/**
* Stop stream output statistics queries for the active streams.
*/
void
svga_end_stream_output_queries(struct svga_context *svga,
unsigned streammask)
{
assert(svga_have_sm5(svga));
if (!svga->in_streamout)
return;
for (unsigned i = 0; i < ARRAY_SIZE(svga->so_queries); i++) {
bool ret;
if (streammask & (1 << i)) {
ret = svga->pipe.end_query(&svga->pipe, svga->so_queries[i]);
}
(void) ret;
}
svga->in_streamout = FALSE;
return;
}
/**
* Return the primitive count returned from the stream output statistics query
* for the specified stream.
*/
unsigned
svga_get_primcount_from_stream_output(struct svga_context *svga,
unsigned stream)
{
unsigned primcount = 0;
union pipe_query_result result;
bool ret;
if (svga->current_so) {
svga_end_stream_output_queries(svga, svga->current_so->streammask);
}
ret = svga->pipe.get_query_result(&svga->pipe,
svga->so_queries[stream],
TRUE, &result);
if (ret)
primcount = result.so_statistics.num_primitives_written;
return primcount;
}

View File

@ -0,0 +1,219 @@
/**********************************************************
* Copyright 2018-2020 VMware, Inc. 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 "pipe/p_context.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_parse.h"
#include "svga_context.h"
#include "svga_shader.h"
static void
svga_set_tess_state(struct pipe_context *pipe,
const float default_outer_level[4],
const float default_inner_level[2])
{
struct svga_context *svga = svga_context(pipe);
unsigned i;
for (i = 0; i < 4; i++) {
svga->curr.default_tesslevels[i] = default_outer_level[i];
}
for (i = 0; i < 2; i++) {
svga->curr.default_tesslevels[i + 4] = default_inner_level[i];
}
}
static void *
svga_create_tcs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct svga_context *svga = svga_context(pipe);
struct svga_tcs_shader *tcs;
tcs = CALLOC_STRUCT(svga_tcs_shader);
if (!tcs)
return NULL;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATETCS);
tcs->base.tokens = tgsi_dup_tokens(templ->tokens);
/* Collect basic info that we'll need later:
*/
tgsi_scan_shader(tcs->base.tokens, &tcs->base.info);
tcs->base.id = svga->debug.shader_id++;
tcs->generic_outputs = svga_get_generic_outputs_mask(&tcs->base.info);
SVGA_STATS_TIME_POP(svga_sws(svga));
return tcs;
}
static void
svga_bind_tcs_state(struct pipe_context *pipe, void *shader)
{
struct svga_tcs_shader *tcs = (struct svga_tcs_shader *) shader;
struct svga_context *svga = svga_context(pipe);
if (tcs == svga->curr.tcs)
return;
svga->curr.tcs = tcs;
svga->dirty |= SVGA_NEW_TCS;
}
static void
svga_delete_tcs_state(struct pipe_context *pipe, void *shader)
{
struct svga_context *svga = svga_context(pipe);
struct svga_tcs_shader *tcs = (struct svga_tcs_shader *) shader;
struct svga_tcs_shader *next_tcs;
struct svga_shader_variant *variant, *tmp;
svga_hwtnl_flush_retry(svga);
assert(tcs->base.parent == NULL);
while (tcs) {
next_tcs = (struct svga_tcs_shader *)tcs->base.next;
for (variant = tcs->base.variants; variant; variant = tmp) {
tmp = variant->next;
/* Check if deleting currently bound shader */
if (variant == svga->state.hw_draw.tcs) {
SVGA_RETRY(svga, svga_set_shader(svga, SVGA3D_SHADERTYPE_HS, NULL));
svga->state.hw_draw.tcs = NULL;
}
svga_destroy_shader_variant(svga, variant);
}
FREE((void *)tcs->base.tokens);
FREE(tcs);
tcs = next_tcs;
}
}
void
svga_cleanup_tcs_state(struct svga_context *svga)
{
if (svga->tcs.passthrough_tcs) {
svga_delete_tcs_state(&svga->pipe, svga->tcs.passthrough_tcs);
}
}
static void *
svga_create_tes_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct svga_context *svga = svga_context(pipe);
struct svga_tes_shader *tes;
tes = CALLOC_STRUCT(svga_tes_shader);
if (!tes)
return NULL;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_CREATETES);
tes->base.tokens = tgsi_dup_tokens(templ->tokens);
/* Collect basic info that we'll need later:
*/
tgsi_scan_shader(tes->base.tokens, &tes->base.info);
tes->base.id = svga->debug.shader_id++;
tes->generic_inputs = svga_get_generic_inputs_mask(&tes->base.info);
SVGA_STATS_TIME_POP(svga_sws(svga));
return tes;
}
static void
svga_bind_tes_state(struct pipe_context *pipe, void *shader)
{
struct svga_tes_shader *tes = (struct svga_tes_shader *) shader;
struct svga_context *svga = svga_context(pipe);
if (tes == svga->curr.tes)
return;
svga->curr.tes = tes;
svga->dirty |= SVGA_NEW_TES;
}
static void
svga_delete_tes_state(struct pipe_context *pipe, void *shader)
{
struct svga_context *svga = svga_context(pipe);
struct svga_tes_shader *tes = (struct svga_tes_shader *) shader;
struct svga_tes_shader *next_tes;
struct svga_shader_variant *variant, *tmp;
svga_hwtnl_flush_retry(svga);
assert(tes->base.parent == NULL);
while (tes) {
next_tes = (struct svga_tes_shader *)tes->base.next;
for (variant = tes->base.variants; variant; variant = tmp) {
tmp = variant->next;
/* Check if deleting currently bound shader */
if (variant == svga->state.hw_draw.tes) {
SVGA_RETRY(svga, svga_set_shader(svga, SVGA3D_SHADERTYPE_DS, NULL));
svga->state.hw_draw.tes = NULL;
}
svga_destroy_shader_variant(svga, variant);
}
FREE((void *)tes->base.tokens);
FREE(tes);
tes = next_tes;
}
}
void
svga_init_ts_functions(struct svga_context *svga)
{
svga->pipe.set_tess_state = svga_set_tess_state;
svga->pipe.create_tcs_state = svga_create_tcs_state;
svga->pipe.bind_tcs_state = svga_bind_tcs_state;
svga->pipe.delete_tcs_state = svga_delete_tcs_state;
svga->pipe.create_tes_state = svga_create_tes_state;
svga->pipe.bind_tes_state = svga_bind_tes_state;
svga->pipe.delete_tes_state = svga_delete_tes_state;
}

View File

@ -166,6 +166,7 @@ svga_delete_vs_state(struct pipe_context *pipe, void *shader)
{ {
struct svga_context *svga = svga_context(pipe); struct svga_context *svga = svga_context(pipe);
struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader; struct svga_vertex_shader *vs = (struct svga_vertex_shader *)shader;
struct svga_vertex_shader *next_vs;
struct svga_shader_variant *variant, *tmp; struct svga_shader_variant *variant, *tmp;
enum pipe_error ret; enum pipe_error ret;
@ -173,6 +174,9 @@ svga_delete_vs_state(struct pipe_context *pipe, void *shader)
assert(vs->base.parent == NULL); assert(vs->base.parent == NULL);
while (vs) {
next_vs = (struct svga_vertex_shader *)vs->base.next;
/* Check if there is a generated geometry shader to go with this /* Check if there is a generated geometry shader to go with this
* vertex shader. If there is, then delete the geometry shader as well. * vertex shader. If there is, then delete the geometry shader as well.
*/ */
@ -204,6 +208,8 @@ svga_delete_vs_state(struct pipe_context *pipe, void *shader)
FREE((void *)vs->base.tokens); FREE((void *)vs->base.tokens);
FREE(vs); FREE(vs);
vs = next_vs;
}
} }

View File

@ -53,7 +53,8 @@ svga_buffer_needs_hw_storage(const struct svga_screen *ss,
const struct pipe_resource *template) const struct pipe_resource *template)
{ {
unsigned bind_mask = (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER | unsigned bind_mask = (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER |
PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT); PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT |
PIPE_BIND_SHADER_BUFFER | PIPE_BIND_COMMAND_ARGS_BUFFER);
if (ss->sws->have_vgpu10) { if (ss->sws->have_vgpu10) {
/* /*
@ -478,6 +479,9 @@ svga_buffer_create(struct pipe_screen *screen,
*/ */
bind_flags |= (PIPE_BIND_VERTEX_BUFFER | bind_flags |= (PIPE_BIND_VERTEX_BUFFER |
PIPE_BIND_INDEX_BUFFER); PIPE_BIND_INDEX_BUFFER);
/* It may be used for shader resource as well. */
bind_flags |= PIPE_BIND_SAMPLER_VIEW;
} }
if (svga_buffer_create_host_surface(ss, sbuf, bind_flags) != PIPE_OK) if (svga_buffer_create_host_surface(ss, sbuf, bind_flags) != PIPE_OK)

View File

@ -175,6 +175,11 @@ svga_buffer_create_host_surface(struct svga_screen *ss,
if (bind_flags & PIPE_BIND_SAMPLER_VIEW) if (bind_flags & PIPE_BIND_SAMPLER_VIEW)
sbuf->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE; sbuf->key.flags |= SVGA3D_SURFACE_BIND_SHADER_RESOURCE;
if (bind_flags & PIPE_BIND_COMMAND_ARGS_BUFFER) {
assert(ss->sws->have_sm5);
sbuf->key.flags |= SVGA3D_SURFACE_DRAWINDIRECT_ARGS;
}
if (!bind_flags && sbuf->b.b.usage == PIPE_USAGE_STAGING) { if (!bind_flags && sbuf->b.b.usage == PIPE_USAGE_STAGING) {
/* This surface is to be used with the /* This surface is to be used with the
* SVGA3D_CMD_DX_TRANSFER_FROM_BUFFER command, and no other * SVGA3D_CMD_DX_TRANSFER_FROM_BUFFER command, and no other

View File

@ -133,26 +133,25 @@ svga_transfer_dma(struct svga_context *svga,
} }
} }
else { else {
int y, h, y_max; int y, h, srcy;
unsigned blockheight = unsigned blockheight =
util_format_get_blockheight(st->base.resource->format); util_format_get_blockheight(st->base.resource->format);
h = st->hw_nblocksy * blockheight; h = st->hw_nblocksy * blockheight;
y_max = st->box.y + st->box.h; srcy = 0;
for (y = st->box.y; y < y_max; y += h) { for (y = 0; y < st->box.h; y += h) {
unsigned offset, length; unsigned offset, length;
void *hw, *sw; void *hw, *sw;
if (y + h > y_max) if (y + h > st->box.h)
h = y_max - y; h = st->box.h - y;
/* Transfer band must be aligned to pixel block boundaries */ /* Transfer band must be aligned to pixel block boundaries */
assert(y % blockheight == 0); assert(y % blockheight == 0);
assert(h % blockheight == 0); assert(h % blockheight == 0);
/* First band starts at the top of the SW buffer. */ offset = y * st->base.stride / blockheight;
offset = (y - st->box.y) * st->base.stride / blockheight;
length = h * st->base.stride / blockheight; length = h * st->base.stride / blockheight;
sw = (uint8_t *) st->swbuf + offset; sw = (uint8_t *) st->swbuf + offset;
@ -160,9 +159,9 @@ svga_transfer_dma(struct svga_context *svga,
if (transfer == SVGA3D_WRITE_HOST_VRAM) { if (transfer == SVGA3D_WRITE_HOST_VRAM) {
unsigned usage = PIPE_TRANSFER_WRITE; unsigned usage = PIPE_TRANSFER_WRITE;
/* Don't write to an in-flight DMA buffer. Synchronize or /* Wait for the previous DMAs to complete */
* discard in-flight storage. */ /* TODO: keep one DMA (at half the size) in the background */
if (y != st->box.y) { if (y) {
svga_context_flush(svga, NULL); svga_context_flush(svga, NULL);
usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE; usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
} }
@ -178,7 +177,7 @@ svga_transfer_dma(struct svga_context *svga,
svga_transfer_dma_band(svga, st, transfer, svga_transfer_dma_band(svga, st, transfer,
st->box.x, y, st->box.z, st->box.x, y, st->box.z,
st->box.w, h, st->box.d, st->box.w, h, st->box.d,
0, 0, 0, flags); 0, srcy, 0, flags);
/* /*
* Prevent the texture contents to be discarded on the next band * Prevent the texture contents to be discarded on the next band
@ -488,6 +487,18 @@ svga_texture_transfer_map_direct(struct svga_context *svga,
svga_context_flush(svga, NULL); svga_context_flush(svga, NULL);
} }
if (map && rebind) {
enum pipe_error ret;
ret = SVGA3D_BindGBSurface(swc, surf);
if (ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_BindGBSurface(swc, surf);
assert(ret == PIPE_OK);
}
svga_context_flush(svga, NULL);
}
/* /*
* Make sure we return NULL if the map fails * Make sure we return NULL if the map fails
*/ */

View File

@ -49,6 +49,10 @@
/* NOTE: this constant may get moved into a svga3d*.h header file */ /* NOTE: this constant may get moved into a svga3d*.h header file */
#define SVGA3D_DX_MAX_RESOURCE_SIZE (128 * 1024 * 1024) #define SVGA3D_DX_MAX_RESOURCE_SIZE (128 * 1024 * 1024)
#ifndef MESA_GIT_SHA1
#define MESA_GIT_SHA1 "(unknown git revision)"
#endif
#ifdef DEBUG #ifdef DEBUG
int SVGA_DEBUG = 0; int SVGA_DEBUG = 0;
@ -249,7 +253,8 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
12 /* 2048x2048 */); 12 /* 2048x2048 */);
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS: case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
return sws->have_vgpu10 ? SVGA3D_MAX_SURFACE_ARRAYSIZE : 0; return sws->have_sm5 ? SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE :
(sws->have_vgpu10 ? SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE : 0);
case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */ case PIPE_CAP_BLEND_EQUATION_SEPARATE: /* req. for GL 1.5 */
return 1; return 1;
@ -266,7 +271,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: case PIPE_CAP_VERTEX_COLOR_UNCLAMPED:
return 1; /* The color outputs of vertex shaders are not clamped */ return 1; /* The color outputs of vertex shaders are not clamped */
case PIPE_CAP_VERTEX_COLOR_CLAMPED: case PIPE_CAP_VERTEX_COLOR_CLAMPED:
return 0; /* The driver can't clamp vertex colors */ return sws->have_vgpu10;
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED: case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
return 0; /* The driver can't clamp fragment colors */ return 0; /* The driver can't clamp fragment colors */
@ -274,10 +279,16 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 1; /* expected for GL_ARB_framebuffer_object */ return 1; /* expected for GL_ARB_framebuffer_object */
case PIPE_CAP_GLSL_FEATURE_LEVEL: case PIPE_CAP_GLSL_FEATURE_LEVEL:
return sws->have_vgpu10 ? 330 : 120; if (sws->have_sm5) {
return 410;
} else if (sws->have_vgpu10) {
return 330;
} else {
return 120;
}
case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY: case PIPE_CAP_GLSL_FEATURE_LEVEL_COMPATIBILITY:
return sws->have_vgpu10 ? 330 : 120; return sws->have_sm5 ? 410 : (sws->have_vgpu10 ? 330 : 120);
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER: case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE: case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE:
@ -303,10 +314,12 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS: case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
return sws->have_vgpu10 ? 4 : 0; return sws->have_vgpu10 ? 4 : 0;
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS: case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
return sws->have_vgpu10 ? SVGA3D_MAX_STREAMOUT_DECLS : 0; return sws->have_sm5 ? SVGA3D_MAX_STREAMOUT_DECLS :
(sws->have_vgpu10 ? SVGA3D_MAX_DX10_STREAMOUT_DECLS : 0);
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME: case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
return sws->have_sm5;
case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS: case PIPE_CAP_STREAM_OUTPUT_INTERLEAVE_BUFFERS:
return 0; return sws->have_sm5;
case PIPE_CAP_TEXTURE_MULTISAMPLE: case PIPE_CAP_TEXTURE_MULTISAMPLE:
return svgascreen->ms_samples ? 1 : 0; return svgascreen->ms_samples ? 1 : 0;
@ -350,7 +363,16 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
return sws->have_sm4_1; return sws->have_sm4_1;
case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS: case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
return sws->have_sm4_1 ? 1 : 0; /* only single-channel textures */ /* SM4_1 supports only single-channel textures where as SM5 supports
* all four channel textures */
return sws->have_sm5 ? 4 :
(sws->have_sm4_1 ? 1 : 0);
case PIPE_CAP_DRAW_INDIRECT:
return sws->have_sm5;
case PIPE_CAP_MAX_VERTEX_STREAMS:
return sws->have_sm5 ? 4 : 0;
case PIPE_CAP_COMPUTE:
return 0;
case PIPE_CAP_MAX_VARYINGS: case PIPE_CAP_MAX_VARYINGS:
return sws->have_vgpu10 ? VGPU10_MAX_FS_INPUTS : 10; return sws->have_vgpu10 ? VGPU10_MAX_FS_INPUTS : 10;
case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT: case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
@ -362,9 +384,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_SHADER_STENCIL_EXPORT: case PIPE_CAP_SHADER_STENCIL_EXPORT:
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE: case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
case PIPE_CAP_TEXTURE_BARRIER: case PIPE_CAP_TEXTURE_BARRIER:
case PIPE_CAP_MAX_VERTEX_STREAMS:
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS: case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
case PIPE_CAP_COMPUTE:
case PIPE_CAP_START_INSTANCE: case PIPE_CAP_START_INSTANCE:
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
case PIPE_CAP_QUERY_PIPELINE_STATISTICS: case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
@ -372,7 +392,6 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_TEXTURE_GATHER_SM5: case PIPE_CAP_TEXTURE_GATHER_SM5:
case PIPE_CAP_TEXTURE_GATHER_OFFSETS: case PIPE_CAP_TEXTURE_GATHER_OFFSETS:
case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION: case PIPE_CAP_TGSI_VS_WINDOW_SPACE_POSITION:
case PIPE_CAP_DRAW_INDIRECT:
case PIPE_CAP_MULTI_DRAW_INDIRECT: case PIPE_CAP_MULTI_DRAW_INDIRECT:
case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS:
case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE: case PIPE_CAP_TGSI_FS_FINE_DERIVATIVE:
@ -410,7 +429,10 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE: case PIPE_CAP_MAX_VERTEX_ATTRIB_STRIDE:
return 2048; return 2048;
case PIPE_CAP_MAX_VIEWPORTS: case PIPE_CAP_MAX_VIEWPORTS:
return 1; assert((!sws->have_vgpu10 && svgascreen->max_viewports == 1) ||
(sws->have_vgpu10 &&
svgascreen->max_viewports == SVGA3D_DX_MAX_VIEWPORTS));
return svgascreen->max_viewports;
case PIPE_CAP_ENDIANNESS: case PIPE_CAP_ENDIANNESS:
return PIPE_ENDIAN_LITTLE; return PIPE_ENDIAN_LITTLE;
@ -427,10 +449,11 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
return sws->have_vgpu10; return sws->have_vgpu10;
case PIPE_CAP_CLEAR_TEXTURE: case PIPE_CAP_CLEAR_TEXTURE:
return sws->have_vgpu10; return sws->have_vgpu10;
case PIPE_CAP_DOUBLES:
return sws->have_sm5;
case PIPE_CAP_UMA: case PIPE_CAP_UMA:
case PIPE_CAP_RESOURCE_FROM_USER_MEMORY: case PIPE_CAP_RESOURCE_FROM_USER_MEMORY:
case PIPE_CAP_DEVICE_RESET_STATUS_QUERY: case PIPE_CAP_DEVICE_RESET_STATUS_QUERY:
case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
case PIPE_CAP_TEXTURE_FLOAT_LINEAR: case PIPE_CAP_TEXTURE_FLOAT_LINEAR:
case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR: case PIPE_CAP_TEXTURE_HALF_FLOAT_LINEAR:
case PIPE_CAP_DEPTH_BOUNDS_TEST: case PIPE_CAP_DEPTH_BOUNDS_TEST:
@ -453,7 +476,6 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY: case PIPE_CAP_GLSL_OPTIMIZE_CONSERVATIVELY:
case PIPE_CAP_FBFETCH: case PIPE_CAP_FBFETCH:
case PIPE_CAP_TGSI_MUL_ZERO_WINS: case PIPE_CAP_TGSI_MUL_ZERO_WINS:
case PIPE_CAP_DOUBLES:
case PIPE_CAP_INT64: case PIPE_CAP_INT64:
case PIPE_CAP_INT64_DIVMOD: case PIPE_CAP_INT64_DIVMOD:
case PIPE_CAP_TGSI_TEX_TXF_LZ: case PIPE_CAP_TGSI_TEX_TXF_LZ:
@ -487,6 +509,9 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param)
return 32; return 32;
case PIPE_CAP_MAX_SHADER_BUFFER_SIZE: case PIPE_CAP_MAX_SHADER_BUFFER_SIZE:
return 1 << 27; return 1 << 27;
/* Verify this once protocol is finalized. Setting it to minimum value. */
case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS:
return sws->have_sm5 ? 30 : 0;
default: default:
return u_pipe_screen_get_param_defaults(screen, param); return u_pipe_screen_get_param_defaults(screen, param);
} }
@ -674,12 +699,12 @@ vgpu10_get_shader_param(struct pipe_screen *screen,
assert(sws->have_vgpu10); assert(sws->have_vgpu10);
(void) sws; /* silence unused var warnings in non-debug builds */ (void) sws; /* silence unused var warnings in non-debug builds */
/* Only VS, GS, FS supported */ if ((!sws->have_sm5) &&
if (shader != PIPE_SHADER_VERTEX && (shader == PIPE_SHADER_TESS_CTRL || shader == PIPE_SHADER_TESS_EVAL))
shader != PIPE_SHADER_GEOMETRY && return 0;
shader != PIPE_SHADER_FRAGMENT) {
if (shader == PIPE_SHADER_COMPUTE)
return 0; return 0;
}
/* NOTE: we do not query the device for any caps/limits at this time */ /* NOTE: we do not query the device for any caps/limits at this time */
@ -697,6 +722,10 @@ vgpu10_get_shader_param(struct pipe_screen *screen,
return VGPU10_MAX_FS_INPUTS; return VGPU10_MAX_FS_INPUTS;
else if (shader == PIPE_SHADER_GEOMETRY) else if (shader == PIPE_SHADER_GEOMETRY)
return VGPU10_MAX_GS_INPUTS; return VGPU10_MAX_GS_INPUTS;
else if (shader == PIPE_SHADER_TESS_CTRL)
return VGPU11_MAX_HS_INPUTS;
else if (shader == PIPE_SHADER_TESS_EVAL)
return VGPU11_MAX_DS_INPUT_CONTROL_POINTS;
else else
return VGPU10_MAX_VS_INPUTS; return VGPU10_MAX_VS_INPUTS;
case PIPE_SHADER_CAP_MAX_OUTPUTS: case PIPE_SHADER_CAP_MAX_OUTPUTS:
@ -704,6 +733,10 @@ vgpu10_get_shader_param(struct pipe_screen *screen,
return VGPU10_MAX_FS_OUTPUTS; return VGPU10_MAX_FS_OUTPUTS;
else if (shader == PIPE_SHADER_GEOMETRY) else if (shader == PIPE_SHADER_GEOMETRY)
return VGPU10_MAX_GS_OUTPUTS; return VGPU10_MAX_GS_OUTPUTS;
else if (shader == PIPE_SHADER_TESS_CTRL)
return VGPU11_MAX_HS_OUTPUTS;
else if (shader == PIPE_SHADER_TESS_EVAL)
return VGPU11_MAX_DS_OUTPUTS;
else else
return VGPU10_MAX_VS_OUTPUTS; return VGPU10_MAX_VS_OUTPUTS;
case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE: case PIPE_SHADER_CAP_MAX_CONST_BUFFER_SIZE:
@ -844,6 +877,8 @@ svga_get_driver_query_info(struct pipe_screen *screen,
PIPE_DRIVER_QUERY_TYPE_UINT64), PIPE_DRIVER_QUERY_TYPE_UINT64),
QUERY("num-bytes-uploaded", SVGA_QUERY_NUM_BYTES_UPLOADED, QUERY("num-bytes-uploaded", SVGA_QUERY_NUM_BYTES_UPLOADED,
PIPE_DRIVER_QUERY_TYPE_BYTES), PIPE_DRIVER_QUERY_TYPE_BYTES),
QUERY("num-command-buffers", SVGA_QUERY_NUM_COMMAND_BUFFERS,
PIPE_DRIVER_QUERY_TYPE_UINT64),
QUERY("command-buffer-size", SVGA_QUERY_COMMAND_BUFFER_SIZE, QUERY("command-buffer-size", SVGA_QUERY_COMMAND_BUFFER_SIZE,
PIPE_DRIVER_QUERY_TYPE_BYTES), PIPE_DRIVER_QUERY_TYPE_BYTES),
QUERY("flush-time", SVGA_QUERY_FLUSH_TIME, QUERY("flush-time", SVGA_QUERY_FLUSH_TIME,
@ -860,6 +895,10 @@ svga_get_driver_query_info(struct pipe_screen *screen,
PIPE_DRIVER_QUERY_TYPE_UINT64), PIPE_DRIVER_QUERY_TYPE_UINT64),
QUERY("num-const-updates", SVGA_QUERY_NUM_CONST_UPDATES, QUERY("num-const-updates", SVGA_QUERY_NUM_CONST_UPDATES,
PIPE_DRIVER_QUERY_TYPE_UINT64), PIPE_DRIVER_QUERY_TYPE_UINT64),
QUERY("num-shader-relocations", SVGA_QUERY_NUM_SHADER_RELOCATIONS,
PIPE_DRIVER_QUERY_TYPE_UINT64),
QUERY("num-surface-relocations", SVGA_QUERY_NUM_SURFACE_RELOCATIONS,
PIPE_DRIVER_QUERY_TYPE_UINT64),
/* running total counters */ /* running total counters */
QUERY("memory-used", SVGA_QUERY_MEMORY_USED, QUERY("memory-used", SVGA_QUERY_MEMORY_USED,
@ -878,6 +917,8 @@ svga_get_driver_query_info(struct pipe_screen *screen,
PIPE_DRIVER_QUERY_TYPE_UINT64), PIPE_DRIVER_QUERY_TYPE_UINT64),
QUERY("num-commands-per-draw", SVGA_QUERY_NUM_COMMANDS_PER_DRAW, QUERY("num-commands-per-draw", SVGA_QUERY_NUM_COMMANDS_PER_DRAW,
PIPE_DRIVER_QUERY_TYPE_FLOAT), PIPE_DRIVER_QUERY_TYPE_FLOAT),
QUERY("shader-mem-used", SVGA_QUERY_SHADER_MEM_USED,
PIPE_DRIVER_QUERY_TYPE_UINT64),
}; };
#undef QUERY #undef QUERY
@ -1012,9 +1053,10 @@ svga_screen_create(struct svga_winsys_screen *sws)
goto error2; goto error2;
} }
debug_printf("%s enabled = %u\n", debug_printf("%s enabled\n",
sws->have_sm4_1 ? "SM4_1" : "VGPU10", sws->have_sm5 ? "SM5" :
sws->have_sm4_1 ? 1 : sws->have_vgpu10); sws->have_sm4_1 ? "SM4_1" :
sws->have_vgpu10 ? "VGPU10" : "VGPU9");
debug_printf("Mesa: %s %s (%s)\n", svga_get_name(screen), debug_printf("Mesa: %s %s (%s)\n", svga_get_name(screen),
PACKAGE_VERSION, MESA_GIT_SHA1); PACKAGE_VERSION, MESA_GIT_SHA1);
@ -1081,13 +1123,23 @@ svga_screen_create(struct svga_winsys_screen *sws)
svgascreen->ms_samples |= 1 << 3; svgascreen->ms_samples |= 1 << 3;
} }
if (sws->have_sm5 && debug_get_bool_option("SVGA_MSAA", TRUE)) {
if (get_bool_cap(sws, SVGA3D_DEVCAP_MULTISAMPLE_8X, FALSE))
svgascreen->ms_samples |= 1 << 7;
}
/* Maximum number of constant buffers */ /* Maximum number of constant buffers */
svgascreen->max_const_buffers = svgascreen->max_const_buffers =
get_uint_cap(sws, SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS, 1); get_uint_cap(sws, SVGA3D_DEVCAP_DX_MAX_CONSTANT_BUFFERS, 1);
svgascreen->max_const_buffers = MIN2(svgascreen->max_const_buffers, svgascreen->max_const_buffers = MIN2(svgascreen->max_const_buffers,
SVGA_MAX_CONST_BUFS); SVGA_MAX_CONST_BUFS);
svgascreen->haveBlendLogicops =
get_bool_cap(sws, SVGA3D_DEVCAP_LOGIC_BLENDOPS, FALSE);
screen->is_format_supported = svga_is_dx_format_supported; screen->is_format_supported = svga_is_dx_format_supported;
svgascreen->max_viewports = SVGA3D_DX_MAX_VIEWPORTS;
} }
else { else {
/* VGPU9 */ /* VGPU9 */
@ -1122,6 +1174,9 @@ svga_screen_create(struct svga_winsys_screen *sws)
/* No multisampling */ /* No multisampling */
svgascreen->ms_samples = 0; svgascreen->ms_samples = 0;
/* Only one viewport */
svgascreen->max_viewports = 1;
} }
/* common VGPU9 / VGPU10 caps */ /* common VGPU9 / VGPU10 caps */

View File

@ -50,10 +50,13 @@ struct svga_screen
/** Device caps */ /** Device caps */
boolean haveProvokingVertex; boolean haveProvokingVertex;
boolean haveLineStipple, haveLineSmooth; boolean haveLineStipple, haveLineSmooth;
boolean haveBlendLogicops;
float maxLineWidth, maxLineWidthAA; float maxLineWidth, maxLineWidthAA;
float maxPointSize; float maxPointSize;
float pointSmoothThreshold; /** Disable point AA for sizes less than this */
unsigned max_color_buffers; unsigned max_color_buffers;
unsigned max_const_buffers; unsigned max_const_buffers;
unsigned max_viewports;
unsigned ms_samples; unsigned ms_samples;
struct { struct {

View File

@ -311,6 +311,9 @@ svga_screen_cache_add(struct svga_screen *svgascreen,
} }
/* Maximum number of invalidate surface commands in a command buffer */
# define SVGA_MAX_SURFACE_TO_INVALIDATE 1000
/** /**
* Called during the screen flush to move all buffers not in a validate list * Called during the screen flush to move all buffers not in a validate list
* into the unused list. * into the unused list.
@ -354,6 +357,7 @@ svga_screen_cache_flush(struct svga_screen *svgascreen,
next = curr->next; next = curr->next;
} }
unsigned nsurf = 0;
curr = cache->validated.next; curr = cache->validated.next;
next = curr->next; next = curr->next;
while (curr != &cache->validated) { while (curr != &cache->validated) {
@ -381,12 +385,14 @@ svga_screen_cache_flush(struct svga_screen *svgascreen,
* this function itself is called inside svga_context_flush(). * this function itself is called inside svga_context_flush().
*/ */
svga->swc->flush(svga->swc, NULL); svga->swc->flush(svga->swc, NULL);
nsurf = 0;
ret = SVGA3D_InvalidateGBSurface(svga->swc, entry->handle); ret = SVGA3D_InvalidateGBSurface(svga->swc, entry->handle);
assert(ret == PIPE_OK); assert(ret == PIPE_OK);
} }
/* add the entry to the invalidated list */ /* add the entry to the invalidated list */
list_add(&entry->head, &cache->invalidated); list_add(&entry->head, &cache->invalidated);
nsurf++;
} }
curr = next; curr = next;
@ -394,6 +400,16 @@ svga_screen_cache_flush(struct svga_screen *svgascreen,
} }
mtx_unlock(&cache->mutex); mtx_unlock(&cache->mutex);
/**
* In some rare cases (when running ARK survival), we hit the max number
* of surface relocations with invalidated surfaces during context flush.
* So if the number of invalidated surface exceeds a certain limit (1000),
* we'll do another winsys flush.
*/
if (nsurf > SVGA_MAX_SURFACE_TO_INVALIDATE) {
svga->swc->flush(svga->swc, NULL);
}
} }

View File

@ -229,22 +229,25 @@ static const enum pipe_swizzle set_XXXY[PIPE_SWIZZLE_MAX] = {
*/ */
void void
svga_init_shader_key_common(const struct svga_context *svga, svga_init_shader_key_common(const struct svga_context *svga,
enum pipe_shader_type shader, enum pipe_shader_type shader_type,
const struct svga_shader *shader,
struct svga_compile_key *key) struct svga_compile_key *key)
{ {
unsigned i, idx = 0; unsigned i, idx = 0;
assert(shader < ARRAY_SIZE(svga->curr.num_sampler_views)); assert(shader_type < ARRAY_SIZE(svga->curr.num_sampler_views));
/* In case the number of samplers and sampler_views doesn't match, /* In case the number of samplers and sampler_views doesn't match,
* loop over the lower of the two counts. * loop over the lower of the two counts.
*/ */
key->num_textures = MAX2(svga->curr.num_sampler_views[shader], key->num_textures = MAX2(svga->curr.num_sampler_views[shader_type],
svga->curr.num_samplers[shader]); svga->curr.num_samplers[shader_type]);
for (i = 0; i < key->num_textures; i++) { for (i = 0; i < key->num_textures; i++) {
struct pipe_sampler_view *view = svga->curr.sampler_views[shader][i]; struct pipe_sampler_view *view = svga->curr.sampler_views[shader_type][i];
const struct svga_sampler_state *sampler = svga->curr.sampler[shader][i]; const struct svga_sampler_state
*sampler = svga->curr.sampler[shader_type][i];
if (view) { if (view) {
assert(view->texture); assert(view->texture);
assert(view->texture->target < (1 << 4)); /* texture_target:4 */ assert(view->texture->target < (1 << 4)); /* texture_target:4 */
@ -304,6 +307,12 @@ svga_init_shader_key_common(const struct svga_context *svga,
if (view->texture->format == PIPE_FORMAT_DXT1_RGB || if (view->texture->format == PIPE_FORMAT_DXT1_RGB ||
view->texture->format == PIPE_FORMAT_DXT1_SRGB) view->texture->format == PIPE_FORMAT_DXT1_SRGB)
swizzle_tab = set_alpha; swizzle_tab = set_alpha;
/* Save the compare function as we need to handle
* depth compare in the shader.
*/
key->tex[i].compare_mode = sampler->compare_mode;
key->tex[i].compare_func = sampler->compare_func;
} }
key->tex[i].swizzle_r = swizzle_tab[view->swizzle_r]; key->tex[i].swizzle_r = swizzle_tab[view->swizzle_r];
@ -314,8 +323,10 @@ svga_init_shader_key_common(const struct svga_context *svga,
if (sampler) { if (sampler) {
if (!sampler->normalized_coords) { if (!sampler->normalized_coords) {
if (view) {
assert(idx < (1 << 5)); /* width_height_idx:5 bitfield */ assert(idx < (1 << 5)); /* width_height_idx:5 bitfield */
key->tex[i].width_height_idx = idx++; key->tex[i].width_height_idx = idx++;
}
key->tex[i].unnormalized = TRUE; key->tex[i].unnormalized = TRUE;
++key->num_unnormalized_coords; ++key->num_unnormalized_coords;
@ -326,6 +337,9 @@ svga_init_shader_key_common(const struct svga_context *svga,
} }
} }
} }
key->clamp_vertex_color = svga->curr.rast ?
svga->curr.rast->templ.clamp_vertex_color : 0;
} }
@ -380,6 +394,8 @@ define_gb_shader_vgpu9(struct svga_context *svga,
variant->gb_shader = sws->shader_create(sws, variant->type, variant->gb_shader = sws->shader_create(sws, variant->type,
variant->tokens, codeLen); variant->tokens, codeLen);
svga->hud.shader_mem_used += codeLen;
if (!variant->gb_shader) if (!variant->gb_shader)
return PIPE_ERROR_OUT_OF_MEMORY; return PIPE_ERROR_OUT_OF_MEMORY;
@ -398,6 +414,7 @@ define_gb_shader_vgpu10(struct svga_context *svga,
{ {
struct svga_winsys_context *swc = svga->swc; struct svga_winsys_context *swc = svga->swc;
enum pipe_error ret; enum pipe_error ret;
unsigned len = codeLen + variant->signatureLen;
/** /**
* Shaders in VGPU10 enabled device reside in the device COTable. * Shaders in VGPU10 enabled device reside in the device COTable.
@ -412,7 +429,11 @@ define_gb_shader_vgpu10(struct svga_context *svga,
/* Create gb memory for the shader and upload the shader code */ /* Create gb memory for the shader and upload the shader code */
variant->gb_shader = swc->shader_create(swc, variant->gb_shader = swc->shader_create(swc,
variant->id, variant->type, variant->id, variant->type,
variant->tokens, codeLen); variant->tokens, codeLen,
variant->signature,
variant->signatureLen);
svga->hud.shader_mem_used += len;
if (!variant->gb_shader) { if (!variant->gb_shader) {
/* Free the shader ID */ /* Free the shader ID */
@ -429,7 +450,8 @@ define_gb_shader_vgpu10(struct svga_context *svga,
* the shader creation and return an error. * the shader creation and return an error.
*/ */
ret = SVGA3D_vgpu10_DefineAndBindShader(swc, variant->gb_shader, ret = SVGA3D_vgpu10_DefineAndBindShader(swc, variant->gb_shader,
variant->id, variant->type, codeLen); variant->id, variant->type,
len);
if (ret != PIPE_OK) if (ret != PIPE_OK)
goto fail; goto fail;
@ -511,7 +533,10 @@ svga_set_shader(struct svga_context *svga,
assert(type == SVGA3D_SHADERTYPE_VS || assert(type == SVGA3D_SHADERTYPE_VS ||
type == SVGA3D_SHADERTYPE_GS || type == SVGA3D_SHADERTYPE_GS ||
type == SVGA3D_SHADERTYPE_PS); type == SVGA3D_SHADERTYPE_PS ||
type == SVGA3D_SHADERTYPE_HS ||
type == SVGA3D_SHADERTYPE_DS ||
type == SVGA3D_SHADERTYPE_CS);
if (svga_have_gb_objects(svga)) { if (svga_have_gb_objects(svga)) {
struct svga_winsys_gb_shader *gbshader = struct svga_winsys_gb_shader *gbshader =
@ -533,7 +558,27 @@ svga_set_shader(struct svga_context *svga,
struct svga_shader_variant * struct svga_shader_variant *
svga_new_shader_variant(struct svga_context *svga, enum pipe_shader_type type) svga_new_shader_variant(struct svga_context *svga, enum pipe_shader_type type)
{ {
struct svga_shader_variant *variant = CALLOC_STRUCT(svga_shader_variant); struct svga_shader_variant *variant;
switch (type) {
case PIPE_SHADER_FRAGMENT:
variant = CALLOC(1, sizeof(struct svga_fs_variant));
break;
case PIPE_SHADER_GEOMETRY:
variant = CALLOC(1, sizeof(struct svga_gs_variant));
break;
case PIPE_SHADER_VERTEX:
variant = CALLOC(1, sizeof(struct svga_vs_variant));
break;
case PIPE_SHADER_TESS_EVAL:
variant = CALLOC(1, sizeof(struct svga_tes_variant));
break;
case PIPE_SHADER_TESS_CTRL:
variant = CALLOC(1, sizeof(struct svga_tcs_variant));
break;
default:
return NULL;
}
if (variant) { if (variant) {
variant->type = svga_shader_type(type); variant->type = svga_shader_type(type);
@ -547,19 +592,11 @@ void
svga_destroy_shader_variant(struct svga_context *svga, svga_destroy_shader_variant(struct svga_context *svga,
struct svga_shader_variant *variant) struct svga_shader_variant *variant)
{ {
enum pipe_error ret = PIPE_OK;
if (svga_have_gb_objects(svga) && variant->gb_shader) { if (svga_have_gb_objects(svga) && variant->gb_shader) {
if (svga_have_vgpu10(svga)) { if (svga_have_vgpu10(svga)) {
struct svga_winsys_context *swc = svga->swc; struct svga_winsys_context *swc = svga->swc;
swc->shader_destroy(swc, variant->gb_shader); swc->shader_destroy(swc, variant->gb_shader);
ret = SVGA3D_vgpu10_DestroyShader(svga->swc, variant->id); SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyShader(svga->swc, variant->id));
if (ret != PIPE_OK) {
/* flush and try again */
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_DestroyShader(svga->swc, variant->id);
assert(ret == PIPE_OK);
}
util_bitmask_clear(svga->shader_id_bm, variant->id); util_bitmask_clear(svga->shader_id_bm, variant->id);
} }
else { else {
@ -570,17 +607,13 @@ svga_destroy_shader_variant(struct svga_context *svga,
} }
else { else {
if (variant->id != UTIL_BITMASK_INVALID_INDEX) { if (variant->id != UTIL_BITMASK_INVALID_INDEX) {
ret = SVGA3D_DestroyShader(svga->swc, variant->id, variant->type); SVGA_RETRY(svga, SVGA3D_DestroyShader(svga->swc, variant->id,
if (ret != PIPE_OK) { variant->type));
/* flush and try again */
svga_context_flush(svga, NULL);
ret = SVGA3D_DestroyShader(svga->swc, variant->id, variant->type);
assert(ret == PIPE_OK);
}
util_bitmask_clear(svga->shader_id_bm, variant->id); util_bitmask_clear(svga->shader_id_bm, variant->id);
} }
} }
FREE(variant->signature);
FREE((unsigned *)variant->tokens); FREE((unsigned *)variant->tokens);
FREE(variant); FREE(variant);
@ -612,6 +645,8 @@ svga_rebind_shaders(struct svga_context *svga)
svga->rebind.flags.vs = 0; svga->rebind.flags.vs = 0;
svga->rebind.flags.gs = 0; svga->rebind.flags.gs = 0;
svga->rebind.flags.fs = 0; svga->rebind.flags.fs = 0;
svga->rebind.flags.tcs = 0;
svga->rebind.flags.tes = 0;
return PIPE_OK; return PIPE_OK;
} }
@ -637,5 +672,19 @@ svga_rebind_shaders(struct svga_context *svga)
} }
svga->rebind.flags.fs = 0; svga->rebind.flags.fs = 0;
if (svga->rebind.flags.tcs && hw->tcs && hw->tcs->gb_shader) {
ret = swc->resource_rebind(swc, NULL, hw->tcs->gb_shader, SVGA_RELOC_READ);
if (ret != PIPE_OK)
return ret;
}
svga->rebind.flags.tcs = 0;
if (svga->rebind.flags.tes && hw->tes && hw->tes->gb_shader) {
ret = swc->resource_rebind(swc, NULL, hw->tes->gb_shader, SVGA_RELOC_READ);
if (ret != PIPE_OK)
return ret;
}
svga->rebind.flags.tes = 0;
return PIPE_OK; return PIPE_OK;
} }

View File

@ -68,6 +68,8 @@ struct svga_compile_key
unsigned need_prescale:1; unsigned need_prescale:1;
unsigned writes_psize:1; unsigned writes_psize:1;
unsigned wide_point:1; unsigned wide_point:1;
unsigned writes_viewport_index:1;
unsigned num_prescale:5;
} gs; } gs;
/* fragment shader only */ /* fragment shader only */
@ -83,15 +85,42 @@ struct svga_compile_key
unsigned alpha_func:4; /**< SVGA3D_CMP_x */ unsigned alpha_func:4; /**< SVGA3D_CMP_x */
unsigned write_color0_to_n_cbufs:4; unsigned write_color0_to_n_cbufs:4;
unsigned aa_point:1; unsigned aa_point:1;
unsigned layer_to_zero:1;
int aa_point_coord_index; int aa_point_coord_index;
float alpha_ref; float alpha_ref;
} fs; } fs;
/* tessellation control shader */
struct {
unsigned vertices_per_patch:8;
enum pipe_prim_type prim_mode:8;
enum pipe_tess_spacing spacing:3;
unsigned vertices_order_cw:1;
unsigned point_mode:1;
unsigned passthrough:1;
} tcs;
/* tessellation evaluation shader */
struct {
unsigned vertices_per_patch:8;
unsigned tessfactor_index:8;
unsigned need_prescale:1;
unsigned need_tessouter:1;
unsigned need_tessinner:1;
} tes;
/* compute shader */
struct {
unsigned grid_size[3];
} cs;
/* any shader type */ /* any shader type */
int8_t generic_remap_table[MAX_GENERIC_VARYING]; int8_t generic_remap_table[MAX_GENERIC_VARYING];
unsigned num_textures:8; unsigned num_textures:8;
unsigned num_unnormalized_coords:8; unsigned num_unnormalized_coords:8;
unsigned clip_plane_enable:PIPE_MAX_CLIP_PLANES; unsigned clip_plane_enable:PIPE_MAX_CLIP_PLANES;
unsigned last_vertex_stage:1;
unsigned clamp_vertex_color:1;
unsigned sprite_origin_lower_left:1; unsigned sprite_origin_lower_left:1;
uint16_t sprite_coord_enable; uint16_t sprite_coord_enable;
struct { struct {
@ -121,6 +150,10 @@ struct svga_token_key {
unsigned writes_psize:1; unsigned writes_psize:1;
unsigned aa_point:1; unsigned aa_point:1;
} gs; } gs;
struct {
unsigned write_position:1;
} vs;
unsigned dynamic_indexing:1;
}; };
/** /**
@ -143,6 +176,10 @@ struct svga_shader_variant
const unsigned *tokens; const unsigned *tokens;
unsigned nr_tokens; unsigned nr_tokens;
/* shader signature */
unsigned signatureLen;
SVGA3dDXShaderSignatureHeader *signature;
/** Per-context shader identifier used with SVGA_3D_CMD_SHADER_DEFINE, /** Per-context shader identifier used with SVGA_3D_CMD_SHADER_DEFINE,
* SVGA_3D_CMD_SET_SHADER and SVGA_3D_CMD_SHADER_DESTROY. * SVGA_3D_CMD_SET_SHADER and SVGA_3D_CMD_SHADER_DESTROY.
*/ */
@ -154,6 +191,18 @@ struct svga_shader_variant
/* GB object buffer containing the bytecode */ /* GB object buffer containing the bytecode */
struct svga_winsys_gb_shader *gb_shader; struct svga_winsys_gb_shader *gb_shader;
/** Next variant */
struct svga_shader_variant *next;
};
/**
* Shader variant for fragment shader
*/
struct svga_fs_variant
{
struct svga_shader_variant base;
boolean uses_flat_interp; /** TRUE if flat interpolation qualifier is boolean uses_flat_interp; /** TRUE if flat interpolation qualifier is
* applied to any of the varyings. * applied to any of the varyings.
*/ */
@ -168,9 +217,56 @@ struct svga_shader_variant
/** For FS-based polygon stipple */ /** For FS-based polygon stipple */
unsigned pstipple_sampler_unit; unsigned pstipple_sampler_unit;
};
/** Next variant */
struct svga_shader_variant *next; /**
* Shader variant for geometry shader
*/
struct svga_gs_variant
{
struct svga_shader_variant base;
};
/**
* Shader variant for vertex shader
*/
struct svga_vs_variant
{
struct svga_shader_variant base;
};
/**
* Shader variant for tessellation evaluation shader
*/
struct svga_tes_variant
{
struct svga_shader_variant base;
enum pipe_prim_type prim_mode:8;
enum pipe_tess_spacing spacing:3;
unsigned vertices_order_cw:1;
unsigned point_mode:1;
};
/**
* Shader variant for tessellation control shader
*/
struct svga_tcs_variant
{
struct svga_shader_variant base;
};
/**
* Shader variant for compute shader
*/
struct svga_cs_variant
{
struct svga_shader_variant base;
}; };
@ -237,6 +333,30 @@ struct svga_geometry_shader
}; };
struct svga_tcs_shader
{
struct svga_shader base;
/** Mask of which generic varying variables are written by this shader */
uint64_t generic_outputs;
};
struct svga_tes_shader
{
struct svga_shader base;
/** Mask of which generic varying variables are written by this shader */
uint64_t generic_inputs;
};
struct svga_compute_shader
{
struct svga_shader base;
};
static inline boolean static inline boolean
svga_compile_keys_equal(const struct svga_compile_key *a, svga_compile_keys_equal(const struct svga_compile_key *a,
const struct svga_compile_key *b) const struct svga_compile_key *b)
@ -264,7 +384,8 @@ svga_remap_generic_index(int8_t remap_table[MAX_GENERIC_VARYING],
void void
svga_init_shader_key_common(const struct svga_context *svga, svga_init_shader_key_common(const struct svga_context *svga,
enum pipe_shader_type shader, enum pipe_shader_type shader_type,
const struct svga_shader *shader,
struct svga_compile_key *key); struct svga_compile_key *key);
struct svga_shader_variant * struct svga_shader_variant *
@ -328,6 +449,12 @@ svga_shader_type(enum pipe_shader_type shader)
return SVGA3D_SHADERTYPE_GS; return SVGA3D_SHADERTYPE_GS;
case PIPE_SHADER_FRAGMENT: case PIPE_SHADER_FRAGMENT:
return SVGA3D_SHADERTYPE_PS; return SVGA3D_SHADERTYPE_PS;
case PIPE_SHADER_TESS_CTRL:
return SVGA3D_SHADERTYPE_HS;
case PIPE_SHADER_TESS_EVAL:
return SVGA3D_SHADERTYPE_DS;
case PIPE_SHADER_COMPUTE:
return SVGA3D_SHADERTYPE_CS;
default: default:
assert(!"Invalid shader type"); assert(!"Invalid shader type");
return SVGA3D_SHADERTYPE_VS; return SVGA3D_SHADERTYPE_VS;
@ -351,4 +478,39 @@ svga_have_gs_streamout(const struct svga_context *svga)
} }
static inline struct svga_fs_variant *
svga_fs_variant(struct svga_shader_variant *variant)
{
assert(!variant || variant->type == SVGA3D_SHADERTYPE_PS);
return (struct svga_fs_variant *)variant;
}
static inline struct svga_tes_variant *
svga_tes_variant(struct svga_shader_variant *variant)
{
assert(!variant || variant->type == SVGA3D_SHADERTYPE_DS);
return (struct svga_tes_variant *)variant;
}
static inline struct svga_cs_variant *
svga_cs_variant(struct svga_shader_variant *variant)
{
assert(!variant || variant->type == SVGA3D_SHADERTYPE_CS);
return (struct svga_cs_variant *)variant;
}
/* Returns TRUE if we are currently using flat shading.
*/
static inline boolean
svga_is_using_flat_shading(const struct svga_context *svga)
{
return
svga->state.hw_draw.fs ?
svga_fs_variant(svga->state.hw_draw.fs)->uses_flat_interp : FALSE;
}
#endif /* SVGA_SHADER_H */ #endif /* SVGA_SHADER_H */

View File

@ -60,19 +60,40 @@ static const struct svga_tracked_state *hw_clear_state[] =
}; };
/* Atoms to update hardware state prior to emitting a draw packet. /**
* Atoms to update hardware state prior to emitting a draw packet
* for VGPU9 device.
*/ */
static const struct svga_tracked_state *hw_draw_state[] = static const struct svga_tracked_state *hw_draw_state_vgpu9[] =
{
&svga_hw_fs,
&svga_hw_vs,
&svga_hw_rss,
&svga_hw_tss,
&svga_hw_tss_binding,
&svga_hw_clip_planes,
&svga_hw_vdecl,
&svga_hw_fs_constants,
&svga_hw_vs_constants,
NULL
};
/**
* Atoms to update hardware state prior to emitting a draw packet
* for VGPU10 device.
* Geometry Shader is new to VGPU10.
* TSS and TSS bindings are replaced by sampler and sampler bindings.
*/
static const struct svga_tracked_state *hw_draw_state_vgpu10[] =
{ {
&svga_need_tgsi_transform, &svga_need_tgsi_transform,
&svga_hw_fs, &svga_hw_fs,
&svga_hw_gs, &svga_hw_gs,
&svga_hw_vs, &svga_hw_vs,
&svga_hw_rss, &svga_hw_rss,
&svga_hw_sampler, /* VGPU10 */ &svga_hw_sampler,
&svga_hw_sampler_bindings, /* VGPU10 */ &svga_hw_sampler_bindings,
&svga_hw_tss, /* pre-VGPU10 */
&svga_hw_tss_binding, /* pre-VGPU10 */
&svga_hw_clip_planes, &svga_hw_clip_planes,
&svga_hw_vdecl, &svga_hw_vdecl,
&svga_hw_fs_constants, &svga_hw_fs_constants,
@ -82,6 +103,33 @@ static const struct svga_tracked_state *hw_draw_state[] =
}; };
/**
* Atoms to update hardware state prior to emitting a draw packet
* for SM5 device.
* TCS and TES Shaders are new to SM5 device.
*/
static const struct svga_tracked_state *hw_draw_state_sm5[] =
{
&svga_need_tgsi_transform,
&svga_hw_fs,
&svga_hw_gs,
&svga_hw_tes,
&svga_hw_tcs,
&svga_hw_vs,
&svga_hw_rss,
&svga_hw_sampler,
&svga_hw_sampler_bindings,
&svga_hw_clip_planes,
&svga_hw_vdecl,
&svga_hw_fs_constants,
&svga_hw_gs_constants,
&svga_hw_tes_constants,
&svga_hw_tcs_constants,
&svga_hw_vs_constants,
NULL
};
static const struct svga_tracked_state *swtnl_draw_state[] = static const struct svga_tracked_state *swtnl_draw_state[] =
{ {
&svga_update_swtnl_draw, &svga_update_swtnl_draw,
@ -89,6 +137,7 @@ static const struct svga_tracked_state *swtnl_draw_state[] =
NULL NULL
}; };
/* Flattens the graph of state dependencies. Could swap the positions /* Flattens the graph of state dependencies. Could swap the positions
* of hw_clear_state and need_swtnl_state without breaking anything. * of hw_clear_state and need_swtnl_state without breaking anything.
*/ */
@ -96,27 +145,26 @@ static const struct svga_tracked_state **state_levels[] =
{ {
need_swtnl_state, need_swtnl_state,
hw_clear_state, hw_clear_state,
hw_draw_state, NULL, /* hw_draw_state, to be set to the right version */
swtnl_draw_state swtnl_draw_state
}; };
static uint64_t
static unsigned check_state(uint64_t a, uint64_t b)
check_state(unsigned a, unsigned b)
{ {
return (a & b); return (a & b);
} }
static void static void
accumulate_state(unsigned *a, unsigned b) accumulate_state(uint64_t *a, uint64_t b)
{ {
*a |= b; *a |= b;
} }
static void static void
xor_states(unsigned *result, unsigned a, unsigned b) xor_states(uint64_t *result, uint64_t a, uint64_t b)
{ {
*result = a ^ b; *result = a ^ b;
} }
@ -125,7 +173,7 @@ xor_states(unsigned *result, unsigned a, unsigned b)
static enum pipe_error static enum pipe_error
update_state(struct svga_context *svga, update_state(struct svga_context *svga,
const struct svga_tracked_state *atoms[], const struct svga_tracked_state *atoms[],
unsigned *state) uint64_t *state)
{ {
#ifdef DEBUG #ifdef DEBUG
boolean debug = TRUE; boolean debug = TRUE;
@ -144,13 +192,13 @@ update_state(struct svga_context *svga,
* state flags which are generated and checked to help ensure * state flags which are generated and checked to help ensure
* state atoms are ordered correctly in the list. * state atoms are ordered correctly in the list.
*/ */
unsigned examined, prev; uint64_t examined, prev;
examined = 0; examined = 0;
prev = *state; prev = *state;
for (i = 0; atoms[i] != NULL; i++) { for (i = 0; atoms[i] != NULL; i++) {
unsigned generated; uint64_t generated;
assert(atoms[i]->dirty); assert(atoms[i]->dirty);
assert(atoms[i]->update); assert(atoms[i]->update);
@ -247,12 +295,7 @@ svga_update_state_retry(struct svga_context *svga, unsigned max_level)
{ {
enum pipe_error ret; enum pipe_error ret;
ret = svga_update_state( svga, max_level ); SVGA_RETRY_OOM(svga, ret, svga_update_state( svga, max_level ));
if (ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = svga_update_state( svga, max_level );
}
return ret == PIPE_OK; return ret == PIPE_OK;
} }
@ -325,3 +368,14 @@ svga_emit_initial_state(struct svga_context *svga)
return PIPE_OK; return PIPE_OK;
} }
} }
void
svga_init_tracked_state(struct svga_context *svga)
{
/* Set the hw_draw_state atom list to the one for the particular gpu version.
*/
state_levels[2] = svga_have_sm5(svga) ? hw_draw_state_sm5 :
(svga_have_vgpu10(svga) ? hw_draw_state_vgpu10 :
hw_draw_state_vgpu9);
}

View File

@ -39,8 +39,8 @@ void svga_destroy_state( struct svga_context *svga );
struct svga_tracked_state { struct svga_tracked_state {
const char *name; const char *name;
unsigned dirty; uint64_t dirty;
enum pipe_error (*update)( struct svga_context *svga, unsigned dirty ); enum pipe_error (*update)( struct svga_context *svga, uint64_t dirty );
}; };
/* NEED_SWTNL /* NEED_SWTNL
@ -61,6 +61,8 @@ extern struct svga_tracked_state svga_need_tgsi_transform;
extern struct svga_tracked_state svga_hw_vs; extern struct svga_tracked_state svga_hw_vs;
extern struct svga_tracked_state svga_hw_fs; extern struct svga_tracked_state svga_hw_fs;
extern struct svga_tracked_state svga_hw_gs; extern struct svga_tracked_state svga_hw_gs;
extern struct svga_tracked_state svga_hw_tcs;
extern struct svga_tracked_state svga_hw_tes;
extern struct svga_tracked_state svga_hw_rss; extern struct svga_tracked_state svga_hw_rss;
extern struct svga_tracked_state svga_hw_pstipple; extern struct svga_tracked_state svga_hw_pstipple;
extern struct svga_tracked_state svga_hw_sampler; extern struct svga_tracked_state svga_hw_sampler;
@ -72,6 +74,8 @@ extern struct svga_tracked_state svga_hw_vdecl;
extern struct svga_tracked_state svga_hw_fs_constants; extern struct svga_tracked_state svga_hw_fs_constants;
extern struct svga_tracked_state svga_hw_gs_constants; extern struct svga_tracked_state svga_hw_gs_constants;
extern struct svga_tracked_state svga_hw_vs_constants; extern struct svga_tracked_state svga_hw_vs_constants;
extern struct svga_tracked_state svga_hw_tes_constants;
extern struct svga_tracked_state svga_hw_tcs_constants;
/* SWTNL_DRAW /* SWTNL_DRAW
*/ */
@ -105,4 +109,15 @@ enum pipe_error svga_reemit_vs_bindings(struct svga_context *svga);
enum pipe_error svga_reemit_fs_bindings(struct svga_context *svga); enum pipe_error svga_reemit_fs_bindings(struct svga_context *svga);
void svga_init_tracked_state(struct svga_context *svga);
void *
svga_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ);
void
svga_bind_fs_state(struct pipe_context *pipe, void *shader);
bool svga_update_compute_state(struct svga_context *svga);
#endif #endif

View File

@ -133,12 +133,13 @@ svga_get_extra_fs_constants(const struct svga_context *svga, float *dest)
* will be returned in 'dest'. * will be returned in 'dest'.
*/ */
static unsigned static unsigned
svga_get_prescale_constants(const struct svga_context *svga, float **dest) svga_get_prescale_constants(const struct svga_context *svga, float **dest,
const struct svga_prescale *prescale)
{ {
memcpy(*dest, svga->state.hw_clear.prescale.scale, 4 * sizeof(float)); memcpy(*dest, prescale->scale, 4 * sizeof(float));
*dest += 4; *dest += 4;
memcpy(*dest, svga->state.hw_clear.prescale.translate, 4 * sizeof(float)); memcpy(*dest, prescale->translate, 4 * sizeof(float));
*dest += 4; *dest += 4;
return 2; return 2;
@ -153,8 +154,8 @@ svga_get_pt_sprite_constants(const struct svga_context *svga, float **dest)
const struct svga_screen *screen = svga_screen(svga->pipe.screen); const struct svga_screen *screen = svga_screen(svga->pipe.screen);
float *dst = *dest; float *dst = *dest;
dst[0] = 1.0 / (svga->curr.viewport.scale[0] * 2); dst[0] = 1.0 / (svga->curr.viewport[0].scale[0] * 2);
dst[1] = 1.0 / (svga->curr.viewport.scale[1] * 2); dst[1] = 1.0 / (svga->curr.viewport[0].scale[1] * 2);
dst[2] = svga->curr.rast->pointsize; dst[2] = svga->curr.rast->pointsize;
dst[3] = screen->maxPointSize; dst[3] = screen->maxPointSize;
*dest = *dest + 4; *dest = *dest + 4;
@ -186,6 +187,7 @@ svga_get_clip_plane_constants(const struct svga_context *svga,
return count; return count;
} }
/** /**
* Emit any extra vertex shader constants into the buffer pointed * Emit any extra vertex shader constants into the buffer pointed
* to by 'dest'. * to by 'dest'.
@ -203,15 +205,16 @@ svga_get_extra_vs_constants(const struct svga_context *svga, float *dest)
/* SVGA_NEW_VS_VARIANT /* SVGA_NEW_VS_VARIANT
*/ */
if (variant->key.vs.need_prescale) { if (variant->key.vs.need_prescale) {
count += svga_get_prescale_constants(svga, &dest); count += svga_get_prescale_constants(svga, &dest,
&svga->state.hw_clear.prescale[0]);
} }
if (variant->key.vs.undo_viewport) { if (variant->key.vs.undo_viewport) {
/* Used to convert window coords back to NDC coords */ /* Used to convert window coords back to NDC coords */
dest[0] = 1.0f / svga->curr.viewport.scale[0]; dest[0] = 1.0f / svga->curr.viewport[0].scale[0];
dest[1] = 1.0f / svga->curr.viewport.scale[1]; dest[1] = 1.0f / svga->curr.viewport[0].scale[1];
dest[2] = -svga->curr.viewport.translate[0]; dest[2] = -svga->curr.viewport[0].translate[0];
dest[3] = -svga->curr.viewport.translate[1]; dest[3] = -svga->curr.viewport[0].translate[1];
dest += 4; dest += 4;
count += 1; count += 1;
} }
@ -250,7 +253,20 @@ svga_get_extra_gs_constants(const struct svga_context *svga, float *dest)
} }
if (variant->key.gs.need_prescale) { if (variant->key.gs.need_prescale) {
count += svga_get_prescale_constants(svga, &dest); unsigned i, num_prescale = 1;
/* If prescale is needed and the geometry shader writes to viewport
* index, then prescale for all viewports will be added to the
* constant buffer.
*/
if (variant->key.gs.writes_viewport_index)
num_prescale = svga->state.hw_clear.num_prescale;
for (i = 0; i < num_prescale; i++) {
count +=
svga_get_prescale_constants(svga, &dest,
&svga->state.hw_clear.prescale[i]);
}
} }
/* SVGA_NEW_CLIP */ /* SVGA_NEW_CLIP */
@ -265,6 +281,77 @@ svga_get_extra_gs_constants(const struct svga_context *svga, float *dest)
} }
/**
* Emit any extra tessellation control shader constants into the
* buffer pointed to by 'dest'.
*/
static unsigned
svga_get_extra_tcs_constants(struct svga_context *svga, float *dest)
{
const struct svga_shader_variant *variant = svga->state.hw_draw.tcs;
unsigned count = 0;
/* SVGA_NEW_CLIP */
count += svga_get_clip_plane_constants(svga, variant, &dest);
/* common constants */
count += svga_get_extra_constants_common(svga, variant,
PIPE_SHADER_TESS_CTRL,
dest);
assert(count <= MAX_EXTRA_CONSTS);
return count;
}
/**
* Emit any extra tessellation evaluation shader constants into
* the buffer pointed to by 'dest'.
*/
static unsigned
svga_get_extra_tes_constants(struct svga_context *svga, float *dest)
{
const struct svga_shader_variant *variant = svga->state.hw_draw.tes;
unsigned count = 0;
if (variant->key.tes.need_prescale) {
count += svga_get_prescale_constants(svga, &dest,
&svga->state.hw_clear.prescale[0]);
}
/* SVGA_NEW_CLIP */
count += svga_get_clip_plane_constants(svga, variant, &dest);
/* common constants */
count += svga_get_extra_constants_common(svga, variant,
PIPE_SHADER_TESS_EVAL,
dest);
assert(count <= MAX_EXTRA_CONSTS);
return count;
}
/**
* Emit any extra compute shader constants into
* the buffer pointed to by 'dest'.
*/
static unsigned
svga_get_extra_cs_constants(struct svga_context *svga, float *dest)
{
const struct svga_shader_variant *variant = svga->state.hw_draw.cs;
unsigned count = 0;
/* common constants */
count += svga_get_extra_constants_common(svga, variant,
PIPE_SHADER_COMPUTE,
dest);
assert(count <= MAX_EXTRA_CONSTS);
return count;
}
/* /*
* Check and emit a range of shader constant registers, trying to coalesce * Check and emit a range of shader constant registers, trying to coalesce
* successive shader constant updates in a single command in order to save * successive shader constant updates in a single command in order to save
@ -490,6 +577,15 @@ emit_constbuf_vgpu10(struct svga_context *svga, enum pipe_shader_type shader)
const struct svga_shader_variant *variant; const struct svga_shader_variant *variant;
unsigned alloc_buf_size; unsigned alloc_buf_size;
assert(shader == PIPE_SHADER_VERTEX ||
shader == PIPE_SHADER_GEOMETRY ||
shader == PIPE_SHADER_FRAGMENT ||
shader == PIPE_SHADER_TESS_CTRL ||
shader == PIPE_SHADER_TESS_EVAL ||
shader == PIPE_SHADER_COMPUTE);
cbuf = &svga->curr.constbufs[shader][0];
switch (shader) { switch (shader) {
case PIPE_SHADER_VERTEX: case PIPE_SHADER_VERTEX:
variant = svga->state.hw_draw.vs; variant = svga->state.hw_draw.vs;
@ -503,6 +599,18 @@ emit_constbuf_vgpu10(struct svga_context *svga, enum pipe_shader_type shader)
variant = svga->state.hw_draw.gs; variant = svga->state.hw_draw.gs;
extra_count = svga_get_extra_gs_constants(svga, (float *) extras); extra_count = svga_get_extra_gs_constants(svga, (float *) extras);
break; break;
case PIPE_SHADER_TESS_CTRL:
variant = svga->state.hw_draw.tcs;
extra_count = svga_get_extra_tcs_constants(svga, (float *) extras);
break;
case PIPE_SHADER_TESS_EVAL:
variant = svga->state.hw_draw.tes;
extra_count = svga_get_extra_tes_constants(svga, (float *) extras);
break;
case PIPE_SHADER_COMPUTE:
variant = svga->state.hw_draw.cs;
extra_count = svga_get_extra_cs_constants(svga, (float *) extras);
break;
default: default:
assert(!"Unexpected shader type"); assert(!"Unexpected shader type");
/* Don't return an error code since we don't want to keep re-trying /* Don't return an error code since we don't want to keep re-trying
@ -706,7 +814,7 @@ emit_consts_vgpu10(struct svga_context *svga, enum pipe_shader_type shader)
} }
static enum pipe_error static enum pipe_error
emit_fs_consts(struct svga_context *svga, unsigned dirty) emit_fs_consts(struct svga_context *svga, uint64_t dirty)
{ {
const struct svga_shader_variant *variant = svga->state.hw_draw.fs; const struct svga_shader_variant *variant = svga->state.hw_draw.fs;
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
@ -741,7 +849,7 @@ struct svga_tracked_state svga_hw_fs_constants =
static enum pipe_error static enum pipe_error
emit_vs_consts(struct svga_context *svga, unsigned dirty) emit_vs_consts(struct svga_context *svga, uint64_t dirty)
{ {
const struct svga_shader_variant *variant = svga->state.hw_draw.vs; const struct svga_shader_variant *variant = svga->state.hw_draw.vs;
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
@ -776,7 +884,7 @@ struct svga_tracked_state svga_hw_vs_constants =
static enum pipe_error static enum pipe_error
emit_gs_consts(struct svga_context *svga, unsigned dirty) emit_gs_consts(struct svga_context *svga, uint64_t dirty)
{ {
const struct svga_shader_variant *variant = svga->state.hw_draw.gs; const struct svga_shader_variant *variant = svga->state.hw_draw.gs;
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
@ -788,7 +896,8 @@ emit_gs_consts(struct svga_context *svga, unsigned dirty)
/* SVGA_NEW_GS_CONST_BUFFER /* SVGA_NEW_GS_CONST_BUFFER
*/ */
if (svga_have_vgpu10(svga)) { assert(svga_have_vgpu10(svga));
/** /**
* If only the rasterizer state has changed and the current geometry * If only the rasterizer state has changed and the current geometry
* shader does not emit wide points, then there is no reason to * shader does not emit wide points, then there is no reason to
@ -798,7 +907,6 @@ emit_gs_consts(struct svga_context *svga, unsigned dirty)
return PIPE_OK; return PIPE_OK;
ret = emit_consts_vgpu10(svga, PIPE_SHADER_GEOMETRY); ret = emit_consts_vgpu10(svga, PIPE_SHADER_GEOMETRY);
}
return ret; return ret;
} }
@ -814,3 +922,66 @@ struct svga_tracked_state svga_hw_gs_constants =
SVGA_NEW_TEXTURE_CONSTS), SVGA_NEW_TEXTURE_CONSTS),
emit_gs_consts emit_gs_consts
}; };
/**
* Emit constant buffer for tessellation control shader
*/
static enum pipe_error
emit_tcs_consts(struct svga_context *svga, uint64_t dirty)
{
const struct svga_shader_variant *variant = svga->state.hw_draw.tcs;
enum pipe_error ret = PIPE_OK;
assert(svga_have_sm5(svga));
/* SVGA_NEW_TCS_VARIANT */
if (!variant)
return PIPE_OK;
/* SVGA_NEW_TCS_CONST_BUFFER */
ret = emit_consts_vgpu10(svga, PIPE_SHADER_TESS_CTRL);
return ret;
}
struct svga_tracked_state svga_hw_tcs_constants =
{
"hw tcs params",
(SVGA_NEW_TCS_CONST_BUFFER |
SVGA_NEW_TCS_VARIANT),
emit_tcs_consts
};
/**
* Emit constant buffer for tessellation evaluation shader
*/
static enum pipe_error
emit_tes_consts(struct svga_context *svga, uint64_t dirty)
{
const struct svga_shader_variant *variant = svga->state.hw_draw.tes;
enum pipe_error ret = PIPE_OK;
assert(svga_have_sm5(svga));
/* SVGA_NEW_TES_VARIANT */
if (!variant)
return PIPE_OK;
ret = emit_consts_vgpu10(svga, PIPE_SHADER_TESS_EVAL);
return ret;
}
struct svga_tracked_state svga_hw_tes_constants =
{
"hw tes params",
(SVGA_NEW_PRESCALE |
SVGA_NEW_TES_CONST_BUFFER |
SVGA_NEW_TES_VARIANT),
emit_tes_consts
};

View File

@ -212,10 +212,14 @@ emit_fb_vgpu10(struct svga_context *svga)
if (curr->cbufs[i]) { if (curr->cbufs[i]) {
struct pipe_surface *s = curr->cbufs[i]; struct pipe_surface *s = curr->cbufs[i];
if (curr->cbufs[i] != hw->cbufs[i]) {
rtv[i] = svga_validate_surface_view(svga, svga_surface(s)); rtv[i] = svga_validate_surface_view(svga, svga_surface(s));
if (rtv[i] == NULL) { if (rtv[i] == NULL) {
return PIPE_ERROR_OUT_OF_MEMORY; return PIPE_ERROR_OUT_OF_MEMORY;
} }
} else {
rtv[i] = svga->state.hw_clear.rtv[i];
}
assert(svga_surface(rtv[i])->view_id != SVGA3D_INVALID_ID); assert(svga_surface(rtv[i])->view_id != SVGA3D_INVALID_ID);
last_rtv = i; last_rtv = i;
@ -233,10 +237,14 @@ emit_fb_vgpu10(struct svga_context *svga)
if (curr->zsbuf) { if (curr->zsbuf) {
struct pipe_surface *s = curr->zsbuf; struct pipe_surface *s = curr->zsbuf;
if (curr->zsbuf != hw->zsbuf) {
dsv = svga_validate_surface_view(svga, svga_surface(curr->zsbuf)); dsv = svga_validate_surface_view(svga, svga_surface(curr->zsbuf));
if (!dsv) { if (!dsv) {
return PIPE_ERROR_OUT_OF_MEMORY; return PIPE_ERROR_OUT_OF_MEMORY;
} }
} else {
dsv = svga->state.hw_clear.dsv;
}
/* Set the rendered-to flag */ /* Set the rendered-to flag */
svga_set_texture_rendered_to(svga_texture(s->texture), svga_set_texture_rendered_to(svga_texture(s->texture),
@ -258,10 +266,6 @@ emit_fb_vgpu10(struct svga_context *svga)
/* number of render targets sent to the device, not including trailing /* number of render targets sent to the device, not including trailing
* unbound render targets. * unbound render targets.
*/ */
svga->state.hw_clear.num_rendertargets = last_rtv + 1;
svga->state.hw_clear.dsv = dsv;
memcpy(svga->state.hw_clear.rtv, rtv, num_color * sizeof(rtv[0]));
for (i = 0; i < ss->max_color_buffers; i++) { for (i = 0; i < ss->max_color_buffers; i++) {
if (hw->cbufs[i] != curr->cbufs[i]) { if (hw->cbufs[i] != curr->cbufs[i]) {
/* propagate the backed view surface before unbinding it */ /* propagate the backed view surface before unbinding it */
@ -270,19 +274,32 @@ emit_fb_vgpu10(struct svga_context *svga)
&svga_surface(hw->cbufs[i])->backed->base, &svga_surface(hw->cbufs[i])->backed->base,
TRUE); TRUE);
} }
else if (svga->state.hw_clear.rtv[i] != hw->cbufs[i] &&
svga->state.hw_clear.rtv[i]) {
/* Free the alternate surface view when it is unbound. */
svga->pipe.surface_destroy(&svga->pipe, svga->state.hw_clear.rtv[i]);
}
pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]); pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
} }
} }
svga->state.hw_clear.num_rendertargets = last_rtv + 1;
memcpy(svga->state.hw_clear.rtv, rtv, num_color * sizeof(rtv[0]));
hw->nr_cbufs = curr->nr_cbufs; hw->nr_cbufs = curr->nr_cbufs;
if (hw->zsbuf != curr->zsbuf) { if (hw->zsbuf != curr->zsbuf) {
/* propagate the backed view surface before unbinding it */ /* propagate the backed view surface before unbinding it */
if (hw->zsbuf && svga_surface(hw->zsbuf)->backed) { if (hw->zsbuf && svga_surface(hw->zsbuf)->backed) {
svga_propagate_surface(svga, &svga_surface(hw->zsbuf)->backed->base, svga_propagate_surface(svga,
&svga_surface(hw->zsbuf)->backed->base,
TRUE); TRUE);
} }
else if (svga->state.hw_clear.dsv != hw->zsbuf && svga->state.hw_clear.dsv) {
/* Free the alternate surface view when it is unbound. */
svga->pipe.surface_destroy(&svga->pipe, svga->state.hw_clear.dsv);
}
pipe_surface_reference(&hw->zsbuf, curr->zsbuf); pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
} }
svga->state.hw_clear.dsv = dsv;
} }
return ret; return ret;
@ -290,7 +307,7 @@ emit_fb_vgpu10(struct svga_context *svga)
static enum pipe_error static enum pipe_error
emit_framebuffer(struct svga_context *svga, unsigned dirty) emit_framebuffer(struct svga_context *svga, uint64_t dirty)
{ {
if (svga_have_vgpu10(svga)) { if (svga_have_vgpu10(svga)) {
return emit_fb_vgpu10(svga); return emit_fb_vgpu10(svga);
@ -383,13 +400,14 @@ struct svga_tracked_state svga_hw_framebuffer =
/*********************************************************************** /***********************************************************************
*/ */
static enum pipe_error static void
emit_viewport( struct svga_context *svga, get_viewport_prescale(struct svga_context *svga,
unsigned dirty ) struct pipe_viewport_state *viewport,
SVGA3dViewport *vp,
struct svga_prescale *prescale)
{ {
const struct pipe_viewport_state *viewport = &svga->curr.viewport;
struct svga_prescale prescale;
SVGA3dRect rect; SVGA3dRect rect;
/* Not sure if this state is relevant with POSITIONT. Probably /* Not sure if this state is relevant with POSITIONT. Probably
* not, but setting to 0,1 avoids some state pingponging. * not, but setting to 0,1 avoids some state pingponging.
*/ */
@ -398,7 +416,6 @@ emit_viewport( struct svga_context *svga,
float flip = -1.0; float flip = -1.0;
boolean degenerate = FALSE; boolean degenerate = FALSE;
boolean invertY = FALSE; boolean invertY = FALSE;
enum pipe_error ret;
float fb_width = (float) svga->curr.framebuffer.width; float fb_width = (float) svga->curr.framebuffer.width;
float fb_height = (float) svga->curr.framebuffer.height; float fb_height = (float) svga->curr.framebuffer.height;
@ -407,9 +424,8 @@ emit_viewport( struct svga_context *svga,
float fy = flip * viewport->scale[1] * -1.0f + viewport->translate[1]; float fy = flip * viewport->scale[1] * -1.0f + viewport->translate[1];
float fw = viewport->scale[0] * 2.0f; float fw = viewport->scale[0] * 2.0f;
float fh = flip * viewport->scale[1] * 2.0f; float fh = flip * viewport->scale[1] * 2.0f;
boolean emit_vgpu10_viewport = FALSE;
memset( &prescale, 0, sizeof(prescale) ); memset(prescale, 0, sizeof(*prescale));
/* Examine gallium viewport transformation and produce a screen /* Examine gallium viewport transformation and produce a screen
* rectangle and possibly vertex shader pre-transformation to * rectangle and possibly vertex shader pre-transformation to
@ -423,14 +439,14 @@ emit_viewport( struct svga_context *svga,
fw, fw,
fh); fh);
prescale.scale[0] = 1.0; prescale->scale[0] = 1.0;
prescale.scale[1] = 1.0; prescale->scale[1] = 1.0;
prescale.scale[2] = 1.0; prescale->scale[2] = 1.0;
prescale.scale[3] = 1.0; prescale->scale[3] = 1.0;
prescale.translate[0] = 0; prescale->translate[0] = 0;
prescale.translate[1] = 0; prescale->translate[1] = 0;
prescale.translate[2] = 0; prescale->translate[2] = 0;
prescale.translate[3] = 0; prescale->translate[3] = 0;
/* Enable prescale to adjust vertex positions to match /* Enable prescale to adjust vertex positions to match
VGPU10 convention only if rasterization is enabled. VGPU10 convention only if rasterization is enabled.
@ -439,12 +455,12 @@ emit_viewport( struct svga_context *svga,
degenerate = TRUE; degenerate = TRUE;
goto out; goto out;
} else { } else {
prescale.enabled = TRUE; prescale->enabled = TRUE;
} }
if (fw < 0) { if (fw < 0) {
prescale.scale[0] *= -1.0f; prescale->scale[0] *= -1.0f;
prescale.translate[0] += -fw; prescale->translate[0] += -fw;
fw = -fw; fw = -fw;
fx = viewport->scale[0] * 1.0f + viewport->translate[0]; fx = viewport->scale[0] * 1.0f + viewport->translate[0];
} }
@ -452,54 +468,54 @@ emit_viewport( struct svga_context *svga,
if (fh < 0.0) { if (fh < 0.0) {
if (svga_have_vgpu10(svga)) { if (svga_have_vgpu10(svga)) {
/* floating point viewport params below */ /* floating point viewport params below */
prescale.translate[1] = fh + fy * 2.0f; prescale->translate[1] = fh + fy * 2.0f;
} }
else { else {
/* integer viewport params below */ /* integer viewport params below */
prescale.translate[1] = fh - 1.0f + fy * 2.0f; prescale->translate[1] = fh - 1.0f + fy * 2.0f;
} }
fh = -fh; fh = -fh;
fy -= fh; fy -= fh;
prescale.scale[1] = -1.0f; prescale->scale[1] = -1.0f;
invertY = TRUE; invertY = TRUE;
} }
if (fx < 0) { if (fx < 0) {
prescale.translate[0] += fx; prescale->translate[0] += fx;
prescale.scale[0] *= fw / (fw + fx); prescale->scale[0] *= fw / (fw + fx);
fw += fx; fw += fx;
fx = 0.0f; fx = 0.0f;
} }
if (fy < 0) { if (fy < 0) {
if (invertY) { if (invertY) {
prescale.translate[1] -= fy; prescale->translate[1] -= fy;
} }
else { else {
prescale.translate[1] += fy; prescale->translate[1] += fy;
} }
prescale.scale[1] *= fh / (fh + fy); prescale->scale[1] *= fh / (fh + fy);
fh += fy; fh += fy;
fy = 0.0f; fy = 0.0f;
} }
if (fx + fw > fb_width) { if (fx + fw > fb_width) {
prescale.scale[0] *= fw / (fb_width - fx); prescale->scale[0] *= fw / (fb_width - fx);
prescale.translate[0] -= fx * (fw / (fb_width - fx)); prescale->translate[0] -= fx * (fw / (fb_width - fx));
prescale.translate[0] += fx; prescale->translate[0] += fx;
fw = fb_width - fx; fw = fb_width - fx;
} }
if (fy + fh > fb_height) { if (fy + fh > fb_height) {
prescale.scale[1] *= fh / (fb_height - fy); prescale->scale[1] *= fh / (fb_height - fy);
if (invertY) { if (invertY) {
float in = fb_height - fy; /* number of vp pixels inside view */ float in = fb_height - fy; /* number of vp pixels inside view */
float out = fy + fh - fb_height; /* number of vp pixels out of view */ float out = fy + fh - fb_height; /* number of vp pixels out of view */
prescale.translate[1] += fy * out / in; prescale->translate[1] += fy * out / in;
} }
else { else {
prescale.translate[1] -= fy * (fh / (fb_height - fy)); prescale->translate[1] -= fy * (fh / (fb_height - fy));
prescale.translate[1] += fy; prescale->translate[1] += fy;
} }
fh = fb_height - fy; fh = fb_height - fy;
} }
@ -566,10 +582,10 @@ emit_viewport( struct svga_context *svga,
if (invertY) if (invertY)
adjust_y = -adjust_y; adjust_y = -adjust_y;
prescale.translate[0] += adjust_x; prescale->translate[0] += adjust_x;
prescale.translate[1] += adjust_y; prescale->translate[1] += adjust_y;
prescale.translate[2] = 0.5; /* D3D clip space */ prescale->translate[2] = 0.5; /* D3D clip space */
prescale.scale[2] = 0.5; /* D3D clip space */ prescale->scale[2] = 0.5; /* D3D clip space */
} }
range_min = viewport->scale[2] * -1.0f + viewport->translate[2]; range_min = viewport->scale[2] * -1.0f + viewport->translate[2];
@ -584,7 +600,7 @@ emit_viewport( struct svga_context *svga,
range_tmp = range_min; range_tmp = range_min;
range_min = range_max; range_min = range_max;
range_max = range_tmp; range_max = range_tmp;
prescale.scale[2] = -prescale.scale[2]; prescale->scale[2] = -prescale->scale[2];
} }
/* If zmin is less than 0, clamp zmin to 0 and adjust the prescale. /* If zmin is less than 0, clamp zmin to 0 and adjust the prescale.
@ -594,21 +610,21 @@ emit_viewport( struct svga_context *svga,
if (range_min < 0.0f) { if (range_min < 0.0f) {
range_min = -0.5f * viewport->scale[2] + 0.5f + viewport->translate[2]; range_min = -0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
range_max = 0.5f * viewport->scale[2] + 0.5f + viewport->translate[2]; range_max = 0.5f * viewport->scale[2] + 0.5f + viewport->translate[2];
prescale.scale[2] *= 2.0f; prescale->scale[2] *= 2.0f;
prescale.translate[2] -= 0.5f; prescale->translate[2] -= 0.5f;
} }
if (prescale.enabled) { if (prescale->enabled) {
float H[2]; float H[2];
float J[2]; float J[2];
int i; int i;
SVGA_DBG(DEBUG_VIEWPORT, SVGA_DBG(DEBUG_VIEWPORT,
"prescale %f,%f %fx%f\n", "prescale %f,%f %fx%f\n",
prescale.translate[0], prescale->translate[0],
prescale.translate[1], prescale->translate[1],
prescale.scale[0], prescale->scale[0],
prescale.scale[1]); prescale->scale[1]);
H[0] = (float)rect.w / 2.0f; H[0] = (float)rect.w / 2.0f;
H[1] = -(float)rect.h / 2.0f; H[1] = -(float)rect.h / 2.0f;
@ -645,16 +661,16 @@ emit_viewport( struct svga_context *svga,
* Overwrite prescale.translate with values for K: * Overwrite prescale.translate with values for K:
*/ */
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
prescale.translate[i] = ((prescale.translate[i] + prescale->translate[i] = ((prescale->translate[i] +
(prescale.scale[i] - 1.0f) * J[i]) / H[i]); (prescale->scale[i] - 1.0f) * J[i]) / H[i]);
} }
SVGA_DBG(DEBUG_VIEWPORT, SVGA_DBG(DEBUG_VIEWPORT,
"clipspace %f,%f %fx%f\n", "clipspace %f,%f %fx%f\n",
prescale.translate[0], prescale->translate[0],
prescale.translate[1], prescale->translate[1],
prescale.scale[0], prescale->scale[0],
prescale.scale[1]); prescale->scale[1]);
} }
out: out:
@ -663,59 +679,90 @@ out:
rect.y = 0; rect.y = 0;
rect.w = 1; rect.w = 1;
rect.h = 1; rect.h = 1;
prescale.enabled = FALSE; prescale->enabled = FALSE;
} }
if (!svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) { vp->x = (float) rect.x;
if (svga_have_vgpu10(svga)) { vp->y = (float) rect.y;
emit_vgpu10_viewport = TRUE; vp->width = (float) rect.w;
vp->height = (float) rect.h;
vp->minDepth = range_min;
vp->maxDepth = range_max;
} }
else {
static enum pipe_error
emit_viewport( struct svga_context *svga,
uint64_t dirty )
{
struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
SVGA3dViewport viewports[SVGA3D_DX_MAX_VIEWPORTS];
struct svga_prescale prescale[SVGA3D_DX_MAX_VIEWPORTS];
unsigned i;
enum pipe_error ret;
unsigned max_viewports = svgascreen->max_viewports;
for (i = 0; i < max_viewports; i++) {
get_viewport_prescale(svga, &svga->curr.viewport[i],
&viewports[i], &prescale[i]);
}
if (memcmp(viewports, svga->state.hw_clear.viewports,
max_viewports * sizeof viewports[0]) != 0) {
if (!svga_have_vgpu10(svga)) {
SVGA3dRect rect;
SVGA3dViewport *vp = &viewports[0];
rect.x = (uint32)vp->x;
rect.y = (uint32)vp->y;
rect.w = (uint32)vp->width;
rect.h = (uint32)vp->height;
ret = SVGA3D_SetViewport(svga->swc, &rect); ret = SVGA3D_SetViewport(svga->swc, &rect);
if (ret != PIPE_OK) if (ret != PIPE_OK)
return ret; return ret;
svga->state.hw_clear.viewport = rect; ret = SVGA3D_SetZRange(svga->swc, vp->minDepth, vp->maxDepth);
} if (ret != PIPE_OK)
} return ret;
if (svga->state.hw_clear.depthrange.zmin != range_min || svga->state.hw_clear.viewport = rect;
svga->state.hw_clear.depthrange.zmax != range_max) svga->state.hw_clear.depthrange.zmin = vp->minDepth;
{ svga->state.hw_clear.depthrange.zmax = vp->maxDepth;
if (svga_have_vgpu10(svga)) {
emit_vgpu10_viewport = TRUE;
} }
else { else {
ret = SVGA3D_SetZRange(svga->swc, range_min, range_max ); ret = SVGA3D_vgpu10_SetViewports(svga->swc, max_viewports,
viewports);
if (ret != PIPE_OK) if (ret != PIPE_OK)
return ret; return ret;
svga->state.hw_clear.depthrange.zmin = range_min;
svga->state.hw_clear.depthrange.zmax = range_max;
} }
memcpy(svga->state.hw_clear.viewports, viewports,
max_viewports * sizeof viewports[0]);
} }
if (emit_vgpu10_viewport) { if (memcmp(prescale, svga->state.hw_clear.prescale,
SVGA3dViewport vp; max_viewports * sizeof prescale[0]) != 0) {
vp.x = (float) rect.x;
vp.y = (float) rect.y;
vp.width = (float) rect.w;
vp.height = (float) rect.h;
vp.minDepth = range_min;
vp.maxDepth = range_max;
ret = SVGA3D_vgpu10_SetViewports(svga->swc, 1, &vp);
if (ret != PIPE_OK)
return ret;
svga->state.hw_clear.viewport = rect;
svga->state.hw_clear.depthrange.zmin = range_min;
svga->state.hw_clear.depthrange.zmax = range_max;
}
if (memcmp(&prescale, &svga->state.hw_clear.prescale, sizeof prescale) != 0) {
svga->dirty |= SVGA_NEW_PRESCALE; svga->dirty |= SVGA_NEW_PRESCALE;
svga->state.hw_clear.prescale = prescale; memcpy(svga->state.hw_clear.prescale, prescale,
max_viewports * sizeof prescale[0]);
/*
* Determine number of unique prescales. This is to minimize the
* if check needed in the geometry shader to identify the prescale
* for the specified viewport.
*/
unsigned last_prescale = SVGA3D_DX_MAX_VIEWPORTS - 1;
unsigned i;
for (i = SVGA3D_DX_MAX_VIEWPORTS-1; i > 0; i--) {
if (memcmp(&svga->state.hw_clear.prescale[i],
&svga->state.hw_clear.prescale[i-1],
sizeof svga->state.hw_clear.prescale[0])) {
break;
}
last_prescale--;
}
svga->state.hw_clear.num_prescale = last_prescale + 1;
} }
return PIPE_OK; return PIPE_OK;
@ -738,32 +785,49 @@ struct svga_tracked_state svga_hw_viewport =
*/ */
static enum pipe_error static enum pipe_error
emit_scissor_rect( struct svga_context *svga, emit_scissor_rect( struct svga_context *svga,
unsigned dirty ) uint64_t dirty )
{ {
const struct pipe_scissor_state *scissor = &svga->curr.scissor; struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
const struct pipe_scissor_state *scissor = svga->curr.scissor;
unsigned max_viewports = svgascreen->max_viewports;
enum pipe_error ret;
if (memcmp(&svga->state.hw_clear.scissors[0], scissor,
max_viewports * sizeof *scissor) != 0) {
if (svga_have_vgpu10(svga)) { if (svga_have_vgpu10(svga)) {
SVGASignedRect rect; SVGASignedRect rect[SVGA3D_DX_MAX_VIEWPORTS];
unsigned i;
rect.left = scissor->minx; for (i = 0; i < max_viewports; i++) {
rect.top = scissor->miny; rect[i].left = scissor[i].minx;
rect.right = scissor->maxx; rect[i].top = scissor[i].miny;
rect.bottom = scissor->maxy; rect[i].right = scissor[i].maxx;
rect[i].bottom = scissor[i].maxy;
}
return SVGA3D_vgpu10_SetScissorRects(svga->swc, 1, &rect); ret = SVGA3D_vgpu10_SetScissorRects(svga->swc, max_viewports, rect);
} }
else { else {
SVGA3dRect rect; SVGA3dRect rect;
rect.x = scissor->minx; rect.x = scissor[0].minx;
rect.y = scissor->miny; rect.y = scissor[0].miny;
rect.w = scissor->maxx - scissor->minx; /* + 1 ?? */ rect.w = scissor[0].maxx - scissor[0].minx; /* + 1 ?? */
rect.h = scissor->maxy - scissor->miny; /* + 1 ?? */ rect.h = scissor[0].maxy - scissor[0].miny; /* + 1 ?? */
return SVGA3D_SetScissorRect(svga->swc, &rect); ret = SVGA3D_SetScissorRect(svga->swc, &rect);
}
} }
if (ret != PIPE_OK)
return ret;
memcpy(svga->state.hw_clear.scissors, scissor,
max_viewports * sizeof *scissor);
}
return PIPE_OK;
}
struct svga_tracked_state svga_hw_scissor = struct svga_tracked_state svga_hw_scissor =
{ {
@ -779,7 +843,7 @@ struct svga_tracked_state svga_hw_scissor =
static enum pipe_error static enum pipe_error
emit_clip_planes( struct svga_context *svga, emit_clip_planes( struct svga_context *svga,
unsigned dirty ) uint64_t dirty )
{ {
unsigned i; unsigned i;
enum pipe_error ret; enum pipe_error ret;

View File

@ -196,8 +196,10 @@ make_fs_key(const struct svga_context *svga,
*/ */
if (svga->curr.gs) { if (svga->curr.gs) {
key->fs.gs_generic_outputs = svga->curr.gs->generic_outputs; key->fs.gs_generic_outputs = svga->curr.gs->generic_outputs;
key->fs.layer_to_zero = !svga->curr.gs->base.info.writes_layer;
} else { } else {
key->fs.vs_generic_outputs = svga->curr.vs->generic_outputs; key->fs.vs_generic_outputs = svga->curr.vs->generic_outputs;
key->fs.layer_to_zero = 1;
} }
/* Only need fragment shader fixup for twoside lighting if doing /* Only need fragment shader fixup for twoside lighting if doing
@ -276,7 +278,7 @@ make_fs_key(const struct svga_context *svga,
* *
* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
*/ */
svga_init_shader_key_common(svga, shader, key); svga_init_shader_key_common(svga, shader, &fs->base, key);
for (i = 0; i < svga->curr.num_samplers[shader]; ++i) { for (i = 0; i < svga->curr.num_samplers[shader]; ++i) {
struct pipe_sampler_view *view = svga->curr.sampler_views[shader][i]; struct pipe_sampler_view *view = svga->curr.sampler_views[shader][i];
@ -317,15 +319,6 @@ make_fs_key(const struct svga_context *svga,
debug_warn_once("Unsupported shadow compare function"); debug_warn_once("Unsupported shadow compare function");
} }
} }
else {
/* For other texture formats, just use the compare func/mode
* as-is. Should be no-ops for color textures. For depth
* textures, we do not get automatic depth compare. We have
* to do it ourselves in the shader. And we don't get PCF.
*/
key->tex[i].compare_mode = sampler->compare_mode;
key->tex[i].compare_func = sampler->compare_func;
}
} }
} }
} }
@ -401,22 +394,26 @@ svga_reemit_fs_bindings(struct svga_context *svga)
static enum pipe_error static enum pipe_error
emit_hw_fs(struct svga_context *svga, unsigned dirty) emit_hw_fs(struct svga_context *svga, uint64_t dirty)
{ {
struct svga_shader_variant *variant = NULL; struct svga_shader_variant *variant = NULL;
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
struct svga_fragment_shader *fs = svga->curr.fs; struct svga_fragment_shader *fs = svga->curr.fs;
struct svga_compile_key key; struct svga_compile_key key;
struct svga_shader *prevShader = NULL; /* shader in the previous stage */
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITFS); SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITFS);
prevShader = svga->curr.gs ?
&svga->curr.gs->base : (svga->curr.tes ?
&svga->curr.tes->base : &svga->curr.vs->base);
/* Disable rasterization if rasterizer_discard flag is set or /* Disable rasterization if rasterizer_discard flag is set or
* vs/gs does not output position. * vs/gs does not output position.
*/ */
svga->disable_rasterizer = svga->disable_rasterizer =
svga->curr.rast->templ.rasterizer_discard || svga->curr.rast->templ.rasterizer_discard ||
(svga->curr.gs && !svga->curr.gs->base.info.writes_position) || !prevShader->info.writes_position;
(!svga->curr.gs && !svga->curr.vs->base.info.writes_position);
/* Set FS to NULL when rasterization is to be disabled */ /* Set FS to NULL when rasterization is to be disabled */
if (svga->disable_rasterizer) { if (svga->disable_rasterizer) {

View File

@ -109,34 +109,45 @@ make_gs_key(struct svga_context *svga, struct svga_compile_key *key)
/* /*
* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
*/ */
svga_init_shader_key_common(svga, PIPE_SHADER_GEOMETRY, key); svga_init_shader_key_common(svga, PIPE_SHADER_GEOMETRY, &gs->base, key);
memcpy(key->generic_remap_table, gs->generic_remap_table, memcpy(key->generic_remap_table, gs->generic_remap_table,
sizeof(gs->generic_remap_table)); sizeof(gs->generic_remap_table));
key->gs.vs_generic_outputs = svga->curr.vs->generic_outputs; key->gs.vs_generic_outputs = svga->curr.vs->generic_outputs;
key->gs.need_prescale = svga->state.hw_clear.prescale.enabled; key->gs.need_prescale = svga->state.hw_clear.prescale[0].enabled;
key->gs.writes_psize = gs->base.info.writes_psize; key->gs.writes_psize = gs->base.info.writes_psize;
key->gs.wide_point = gs->wide_point; key->gs.wide_point = gs->wide_point;
key->gs.writes_viewport_index = gs->base.info.writes_viewport_index;
if (key->gs.writes_viewport_index) {
key->gs.num_prescale = svga->state.hw_clear.num_prescale;
} else {
key->gs.num_prescale = 1;
}
key->sprite_coord_enable = svga->curr.rast->templ.sprite_coord_enable; key->sprite_coord_enable = svga->curr.rast->templ.sprite_coord_enable;
key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode key->sprite_origin_lower_left = (svga->curr.rast->templ.sprite_coord_mode
== PIPE_SPRITE_COORD_LOWER_LEFT); == PIPE_SPRITE_COORD_LOWER_LEFT);
/* SVGA_NEW_RAST */ /* SVGA_NEW_RAST */
key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable; key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable;
/* Mark this as the last shader in the vertex processing stage */
key->last_vertex_stage = 1;
} }
static enum pipe_error static enum pipe_error
emit_hw_gs(struct svga_context *svga, unsigned dirty) emit_hw_gs(struct svga_context *svga, uint64_t dirty)
{ {
struct svga_shader_variant *variant; struct svga_shader_variant *variant;
struct svga_geometry_shader *gs = svga->curr.gs; struct svga_geometry_shader *gs = svga->curr.gs;
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
struct svga_compile_key key; struct svga_compile_key key;
assert(svga_have_vgpu10(svga));
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITGS); SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITGS);
/* If there's a user-defined GS, we should have a pointer to a derived /* If there's a user-defined GS, we should have a pointer to a derived

View File

@ -33,7 +33,7 @@
static enum pipe_error static enum pipe_error
update_need_swvfetch(struct svga_context *svga, unsigned dirty) update_need_swvfetch(struct svga_context *svga, uint64_t dirty)
{ {
if (!svga->curr.velems) { if (!svga->curr.velems) {
/* No vertex elements bound. */ /* No vertex elements bound. */
@ -58,7 +58,7 @@ struct svga_tracked_state svga_update_need_swvfetch =
static enum pipe_error static enum pipe_error
update_need_pipeline(struct svga_context *svga, unsigned dirty) update_need_pipeline(struct svga_context *svga, uint64_t dirty)
{ {
boolean need_pipeline = FALSE; boolean need_pipeline = FALSE;
struct svga_vertex_shader *vs = svga->curr.vs; struct svga_vertex_shader *vs = svga->curr.vs;
@ -156,7 +156,7 @@ struct svga_tracked_state svga_update_need_pipeline =
static enum pipe_error static enum pipe_error
update_need_swtnl(struct svga_context *svga, unsigned dirty) update_need_swtnl(struct svga_context *svga, uint64_t dirty)
{ {
boolean need_swtnl; boolean need_swtnl;

View File

@ -97,7 +97,7 @@ translate_fill_mode(unsigned fill)
* the "to" state. * the "to" state.
*/ */
static enum pipe_error static enum pipe_error
emit_rss_vgpu9(struct svga_context *svga, unsigned dirty) emit_rss_vgpu9(struct svga_context *svga, uint64_t dirty)
{ {
struct svga_screen *screen = svga_screen(svga->pipe.screen); struct svga_screen *screen = svga_screen(svga->pipe.screen);
struct rs_queue queue; struct rs_queue queue;
@ -363,7 +363,7 @@ get_no_depth_stencil_test_state(struct svga_context *svga)
static enum pipe_error static enum pipe_error
emit_rss_vgpu10(struct svga_context *svga, unsigned dirty) emit_rss_vgpu10(struct svga_context *svga, uint64_t dirty)
{ {
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
@ -487,7 +487,7 @@ emit_rss_vgpu10(struct svga_context *svga, unsigned dirty)
static enum pipe_error static enum pipe_error
emit_rss(struct svga_context *svga, unsigned dirty) emit_rss(struct svga_context *svga, uint64_t dirty)
{ {
if (svga_have_vgpu10(svga)) { if (svga_have_vgpu10(svga)) {
return emit_rss_vgpu10(svga, dirty); return emit_rss_vgpu10(svga, dirty);

View File

@ -131,7 +131,7 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
if (sv->id == SVGA3D_INVALID_ID) { if (sv->id == SVGA3D_INVALID_ID) {
struct svga_screen *ss = svga_screen(svga->pipe.screen); struct svga_screen *ss = svga_screen(svga->pipe.screen);
struct pipe_resource *texture = sv->base.texture; struct pipe_resource *texture = sv->base.texture;
struct svga_winsys_surface *surface = svga_resource_handle(texture); struct svga_winsys_surface *surface;
SVGA3dSurfaceFormat format; SVGA3dSurfaceFormat format;
SVGA3dResourceType resourceDim; SVGA3dResourceType resourceDim;
SVGA3dShaderResourceViewDesc viewDesc; SVGA3dShaderResourceViewDesc viewDesc;
@ -154,6 +154,7 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
svga_translate_texture_buffer_view_format(viewFormat, svga_translate_texture_buffer_view_format(viewFormat,
&format, &format,
&pf_flags); &pf_flags);
surface = svga_buffer_handle(svga, texture, PIPE_BIND_SAMPLER_VIEW);
} }
else { else {
format = svga_translate_format(ss, viewFormat, format = svga_translate_format(ss, viewFormat,
@ -161,6 +162,8 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
/* Convert the format to a sampler-friendly format, if needed */ /* Convert the format to a sampler-friendly format, if needed */
format = svga_sampler_format(format); format = svga_sampler_format(format);
surface = svga_texture(texture)->handle;
} }
assert(format != SVGA3D_FORMAT_INVALID); assert(format != SVGA3D_FORMAT_INVALID);
@ -234,15 +237,14 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
static enum pipe_error static enum pipe_error
update_sampler_resources(struct svga_context *svga, unsigned dirty) update_sampler_resources(struct svga_context *svga, uint64_t dirty)
{ {
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
enum pipe_shader_type shader; enum pipe_shader_type shader;
if (!svga_have_vgpu10(svga)) assert(svga_have_vgpu10(svga));
return PIPE_OK;
for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) {
SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS]; SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS];
struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS]; struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS]; struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
@ -349,7 +351,8 @@ update_sampler_resources(struct svga_context *svga, unsigned dirty)
/* Handle polygon stipple sampler view */ /* Handle polygon stipple sampler view */
if (svga->curr.rast->templ.poly_stipple_enable) { if (svga->curr.rast->templ.poly_stipple_enable) {
const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit; const unsigned unit =
svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
struct svga_pipe_sampler_view *sv = svga->polygon_stipple.sampler_view; struct svga_pipe_sampler_view *sv = svga->polygon_stipple.sampler_view;
struct svga_winsys_surface *surface; struct svga_winsys_surface *surface;
@ -385,15 +388,14 @@ struct svga_tracked_state svga_hw_sampler_bindings = {
static enum pipe_error static enum pipe_error
update_samplers(struct svga_context *svga, unsigned dirty ) update_samplers(struct svga_context *svga, uint64_t dirty )
{ {
enum pipe_error ret = PIPE_OK; enum pipe_error ret = PIPE_OK;
enum pipe_shader_type shader; enum pipe_shader_type shader;
if (!svga_have_vgpu10(svga)) assert(svga_have_vgpu10(svga));
return PIPE_OK;
for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) { for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) {
const unsigned count = svga->curr.num_samplers[shader]; const unsigned count = svga->curr.num_samplers[shader];
SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS]; SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS];
unsigned i; unsigned i;
@ -404,7 +406,8 @@ update_samplers(struct svga_context *svga, unsigned dirty )
/* _NEW_FS */ /* _NEW_FS */
if (shader == PIPE_SHADER_FRAGMENT) { if (shader == PIPE_SHADER_FRAGMENT) {
struct svga_shader_variant *fs = svga->state.hw_draw.fs; struct svga_fs_variant *fs =
svga_fs_variant(svga->state.hw_draw.fs);
/* If the fragment shader is doing the shadow comparison /* If the fragment shader is doing the shadow comparison
* for this texture unit, don't enable shadow compare in * for this texture unit, don't enable shadow compare in
* the texture sampler state. * the texture sampler state.
@ -449,7 +452,8 @@ update_samplers(struct svga_context *svga, unsigned dirty )
/* Handle polygon stipple sampler texture */ /* Handle polygon stipple sampler texture */
if (svga->curr.rast->templ.poly_stipple_enable) { if (svga->curr.rast->templ.poly_stipple_enable) {
const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit; const unsigned unit =
svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
struct svga_sampler_state *sampler = svga->polygon_stipple.sampler; struct svga_sampler_state *sampler = svga->polygon_stipple.sampler;
assert(sampler); assert(sampler);

View File

@ -29,7 +29,10 @@
#include "util/u_simple_shaders.h" #include "util/u_simple_shaders.h"
#include "tgsi/tgsi_ureg.h" #include "tgsi/tgsi_ureg.h"
#include "tgsi/tgsi_point_sprite.h" #include "tgsi/tgsi_point_sprite.h"
#include "tgsi/tgsi_dynamic_indexing.h"
#include "tgsi/tgsi_vpos.h"
#include "tgsi/tgsi_dump.h" #include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_info.h"
#include "svga_context.h" #include "svga_context.h"
#include "svga_shader.h" #include "svga_shader.h"
@ -49,6 +52,171 @@ bind_gs_state(struct svga_context *svga,
} }
static void
insert_at_head(struct svga_shader *head, struct svga_shader *shader)
{
shader->parent = head;
shader->next = head->next;
head->next = shader;
}
/**
* Bind shader
*/
static void
bind_shader(struct svga_context *svga,
const enum pipe_shader_type shader_type,
struct svga_shader *shader)
{
switch (shader_type) {
case PIPE_SHADER_VERTEX:
svga->pipe.bind_vs_state(&svga->pipe, shader);
break;
case PIPE_SHADER_FRAGMENT:
/**
* Avoid pipe->bind_fs_state call because it goes through aapoint
* layer. We loose linked list of all transformed shaders if aapoint
* is used.
*/
svga_bind_fs_state(&svga->pipe, shader);
break;
case PIPE_SHADER_GEOMETRY:
svga->pipe.bind_gs_state(&svga->pipe, shader);
break;
case PIPE_SHADER_TESS_CTRL:
svga->pipe.bind_tcs_state(&svga->pipe, shader);
break;
case PIPE_SHADER_TESS_EVAL:
svga->pipe.bind_tes_state(&svga->pipe, shader);
break;
default:
return;
}
}
/**
* Create shader
*/
static void *
create_shader(struct svga_context *svga,
const enum pipe_shader_type shader_type,
struct pipe_shader_state *state)
{
switch (shader_type) {
case PIPE_SHADER_VERTEX:
return svga->pipe.create_vs_state(&svga->pipe, state);
case PIPE_SHADER_FRAGMENT:
/**
* Avoid pipe->create_fs_state call because it goes through aapoint
* layer. We loose linked list of all transformed shaders if aapoint
* is used.
*/
return svga_create_fs_state(&svga->pipe, state);
case PIPE_SHADER_GEOMETRY:
return svga->pipe.create_gs_state(&svga->pipe, state);
case PIPE_SHADER_TESS_CTRL:
return svga->pipe.create_tcs_state(&svga->pipe, state);
case PIPE_SHADER_TESS_EVAL:
return svga->pipe.create_tes_state(&svga->pipe, state);
default:
return NULL;
}
}
static void
write_vpos(struct svga_context *svga,
struct svga_shader *shader)
{
struct svga_token_key key;
boolean use_existing = FALSE;
struct svga_shader *transform_shader;
const struct tgsi_shader_info *info = &shader->info;
/* Create a token key */
memset(&key, 0, sizeof key);
key.vs.write_position = 1;
if (shader->next) {
transform_shader = svga_search_shader_token_key(shader->next, &key);
if (transform_shader) {
use_existing = TRUE;
}
}
if (!use_existing) {
struct pipe_shader_state state;
struct tgsi_token *new_tokens = NULL;
new_tokens = tgsi_write_vpos(shader->tokens,
info->immediate_count);
if (!new_tokens)
return;
pipe_shader_state_from_tgsi(&state, new_tokens);
transform_shader = create_shader(svga, info->processor, &state);
insert_at_head(shader, transform_shader);
FREE(new_tokens);
}
transform_shader->token_key = key;
bind_shader(svga, info->processor, transform_shader);
}
/**
* transform_dynamic_indexing searches shader variant list to see if
* we have transformed shader for dynamic indexing and reuse/bind it. If we
* don't have transformed shader, then it will create new shader from which
* dynamic indexing will be removed. It will also be added to the shader
* variant list and this new shader will be bind to current svga state.
*/
static void
transform_dynamic_indexing(struct svga_context *svga,
struct svga_shader *shader)
{
struct svga_token_key key;
boolean use_existing = FALSE;
struct svga_shader *transform_shader;
const struct tgsi_shader_info *info = &shader->info;
/* Create a token key */
memset(&key, 0, sizeof key);
key.dynamic_indexing = 1;
if (shader->next) {
transform_shader = svga_search_shader_token_key(shader->next, &key);
if (transform_shader) {
use_existing = TRUE;
}
}
struct tgsi_token *new_tokens = NULL;
if (!use_existing) {
struct pipe_shader_state state;
new_tokens = tgsi_remove_dynamic_indexing(shader->tokens,
info->const_buffers_declared,
info->samplers_declared,
info->immediate_count);
if (!new_tokens)
return;
pipe_shader_state_from_tgsi(&state, new_tokens);
transform_shader = create_shader(svga, info->processor, &state);
insert_at_head(shader, transform_shader);
}
transform_shader->token_key = key;
bind_shader(svga, info->processor, transform_shader);
if (new_tokens)
FREE(new_tokens);
}
/** /**
* emulate_point_sprite searches the shader variants list to see it there is * emulate_point_sprite searches the shader variants list to see it there is
* a shader variant with a token string that matches the emulation * a shader variant with a token string that matches the emulation
@ -233,18 +401,49 @@ add_point_sprite_shader(struct svga_context *svga)
return &new_gs->base; return &new_gs->base;
} }
static boolean
has_dynamic_indexing(const struct tgsi_shader_info *info)
{
return (info->dim_indirect_files & (1u << TGSI_FILE_CONSTANT)) ||
(info->indirect_files & (1u << TGSI_FILE_SAMPLER));
}
/* update_tgsi_transform provides a hook to transform a shader if needed. /* update_tgsi_transform provides a hook to transform a shader if needed.
*/ */
static enum pipe_error static enum pipe_error
update_tgsi_transform(struct svga_context *svga, unsigned dirty) update_tgsi_transform(struct svga_context *svga, uint64_t dirty)
{ {
struct svga_geometry_shader *gs = svga->curr.user_gs; /* current gs */ struct svga_geometry_shader *gs = svga->curr.user_gs; /* current gs */
struct svga_vertex_shader *vs = svga->curr.vs; /* currently bound vs */ struct svga_vertex_shader *vs = svga->curr.vs; /* currently bound vs */
struct svga_fragment_shader *fs = svga->curr.fs; /* currently bound fs */
struct svga_tcs_shader *tcs = svga->curr.tcs; /* currently bound tcs */
struct svga_tes_shader *tes = svga->curr.tes; /* currently bound tes */
struct svga_shader *orig_gs; /* original gs */ struct svga_shader *orig_gs; /* original gs */
struct svga_shader *new_gs; /* new gs */ struct svga_shader *new_gs; /* new gs */
if (!svga_have_vgpu10(svga)) assert(svga_have_vgpu10(svga));
return PIPE_OK;
if (vs->base.info.num_outputs == 0) {
write_vpos(svga, &vs->base);
}
if (vs && has_dynamic_indexing(&vs->base.info)) {
transform_dynamic_indexing(svga, &vs->base);
}
if (fs && has_dynamic_indexing(&fs->base.info)) {
transform_dynamic_indexing(svga, &fs->base);
}
if (gs && has_dynamic_indexing(&gs->base.info)) {
transform_dynamic_indexing(svga, &gs->base);
}
if (tcs && has_dynamic_indexing(&tcs->base.info)) {
transform_dynamic_indexing(svga, &tcs->base);
}
if (tes && has_dynamic_indexing(&tes->base.info)) {
transform_dynamic_indexing(svga, &tes->base);
}
if (svga->curr.reduced_prim == PIPE_PRIM_POINTS) { if (svga->curr.reduced_prim == PIPE_PRIM_POINTS) {
/* If the current prim type is POINTS and the current geometry shader /* If the current prim type is POINTS and the current geometry shader

View File

@ -0,0 +1,392 @@
/**********************************************************
* Copyright 2018-2020 VMware, Inc. 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 "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_simple_shaders.h"
#include "svga_context.h"
#include "svga_cmd.h"
#include "svga_tgsi.h"
#include "svga_shader.h"
/**
* Translate TGSI shader into an svga shader variant.
*/
static enum pipe_error
compile_tcs(struct svga_context *svga,
struct svga_tcs_shader *tcs,
const struct svga_compile_key *key,
struct svga_shader_variant **out_variant)
{
struct svga_shader_variant *variant;
enum pipe_error ret = PIPE_ERROR;
variant = svga_tgsi_vgpu10_translate(svga, &tcs->base, key,
PIPE_SHADER_TESS_CTRL);
if (!variant)
return PIPE_ERROR;
ret = svga_define_shader(svga, variant);
if (ret != PIPE_OK) {
svga_destroy_shader_variant(svga, variant);
return ret;
}
*out_variant = variant;
return PIPE_OK;
}
static void
make_tcs_key(struct svga_context *svga, struct svga_compile_key *key)
{
struct svga_tcs_shader *tcs = svga->curr.tcs;
memset(key, 0, sizeof *key);
/*
* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
*/
svga_init_shader_key_common(svga, PIPE_SHADER_TESS_CTRL, &tcs->base, key);
/* SVGA_NEW_TCS_PARAM */
key->tcs.vertices_per_patch = svga->curr.vertices_per_patch;
/* The tessellator parameters come from the layout section in the
* tessellation evaluation shader. Get these parameters from the
* current tessellation evaluation shader variant.
* Note: this requires the tessellation evaluation shader to be
* compiled first.
*/
struct svga_tes_variant *tes = svga_tes_variant(svga->state.hw_draw.tes);
key->tcs.prim_mode = tes->prim_mode;
key->tcs.spacing = tes->spacing;
key->tcs.vertices_order_cw = tes->vertices_order_cw;
key->tcs.point_mode = tes->point_mode;
if (svga->tcs.passthrough)
key->tcs.passthrough = 1;
key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable;
/* tcs is always followed by tes */
key->last_vertex_stage = 0;
}
static enum pipe_error
emit_hw_tcs(struct svga_context *svga, uint64_t dirty)
{
struct svga_shader_variant *variant;
struct svga_tcs_shader *tcs = svga->curr.tcs;
enum pipe_error ret = PIPE_OK;
struct svga_compile_key key;
assert(svga_have_sm5(svga));
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITTCS);
if (!tcs) {
/* If there is no active tcs, then there should not be
* active tes either
*/
assert(!svga->curr.tes);
if (svga->state.hw_draw.tcs != NULL) {
/** The previous tessellation control shader is made inactive.
* Needs to unbind the tessellation control shader.
*/
ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_HS, NULL);
if (ret != PIPE_OK)
goto done;
svga->state.hw_draw.tcs = NULL;
}
goto done;
}
make_tcs_key(svga, &key);
/* See if we already have a TCS variant that matches the key */
variant = svga_search_shader_key(&tcs->base, &key);
if (!variant) {
ret = compile_tcs(svga, tcs, &key, &variant);
if (ret != PIPE_OK)
goto done;
/* insert the new variant at head of linked list */
assert(variant);
variant->next = tcs->base.variants;
tcs->base.variants = variant;
}
if (variant != svga->state.hw_draw.tcs) {
/* Bind the new variant */
ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_HS, variant);
if (ret != PIPE_OK)
goto done;
svga->rebind.flags.tcs = FALSE;
svga->dirty |= SVGA_NEW_TCS_VARIANT;
svga->state.hw_draw.tcs = variant;
}
done:
SVGA_STATS_TIME_POP(svga_sws(svga));
return ret;
}
struct svga_tracked_state svga_hw_tcs =
{
"tessellation control shader (hwtnl)",
(SVGA_NEW_VS |
SVGA_NEW_TCS |
SVGA_NEW_TES |
SVGA_NEW_TEXTURE_BINDING |
SVGA_NEW_SAMPLER |
SVGA_NEW_RAST),
emit_hw_tcs
};
/**
* Translate TGSI shader into an svga shader variant.
*/
static enum pipe_error
compile_tes(struct svga_context *svga,
struct svga_tes_shader *tes,
const struct svga_compile_key *key,
struct svga_shader_variant **out_variant)
{
struct svga_shader_variant *variant;
enum pipe_error ret = PIPE_ERROR;
variant = svga_tgsi_vgpu10_translate(svga, &tes->base, key,
PIPE_SHADER_TESS_EVAL);
if (!variant)
return PIPE_ERROR;
ret = svga_define_shader(svga, variant);
if (ret != PIPE_OK) {
svga_destroy_shader_variant(svga, variant);
return ret;
}
*out_variant = variant;
return PIPE_OK;
}
static void
make_tes_key(struct svga_context *svga, struct svga_compile_key *key)
{
struct svga_tes_shader *tes = svga->curr.tes;
memset(key, 0, sizeof *key);
/*
* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
*/
svga_init_shader_key_common(svga, PIPE_SHADER_TESS_EVAL, &tes->base, key);
assert(svga->curr.tcs);
key->tes.vertices_per_patch =
svga->curr.tcs->base.info.properties[TGSI_PROPERTY_TCS_VERTICES_OUT];
key->tes.need_prescale = svga->state.hw_clear.prescale[0].enabled &&
(svga->curr.gs == NULL);
/* tcs emits tessellation factors as extra outputs.
* Since tes depends on them, save the tessFactor output index
* from tcs in the tes compile key, so that if a different
* tcs is bound and if the tessFactor index is different,
* a different tes variant will be generated.
*/
key->tes.tessfactor_index = svga->curr.tcs->base.info.num_outputs;
key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable;
/* This is the last vertex stage if there is no geometry shader. */
key->last_vertex_stage = !svga->curr.gs;
key->tes.need_tessinner = 0;
key->tes.need_tessouter = 0;
for (int i = 0; i < svga->curr.tcs->base.info.num_outputs; i++) {
switch (svga->curr.tcs->base.info.output_semantic_name[i]) {
case TGSI_SEMANTIC_TESSOUTER:
key->tes.need_tessouter = 1;
break;
case TGSI_SEMANTIC_TESSINNER:
key->tes.need_tessinner = 1;
break;
default:
break;
}
}
}
static void
get_passthrough_tcs(struct svga_context *svga)
{
if (svga->tcs.passthrough_tcs &&
svga->tcs.vs == svga->curr.vs &&
svga->tcs.tes == svga->curr.tes &&
svga->tcs.vertices_per_patch == svga->curr.vertices_per_patch) {
svga->pipe.bind_tcs_state(&svga->pipe,
svga->tcs.passthrough_tcs);
}
else {
struct svga_tcs_shader *new_tcs;
/* delete older passthrough shader*/
if (svga->tcs.passthrough_tcs) {
svga->pipe.delete_tcs_state(&svga->pipe,
svga->tcs.passthrough_tcs);
}
new_tcs = (struct svga_tcs_shader *)
util_make_tess_ctrl_passthrough_shader(&svga->pipe,
svga->curr.vs->base.info.num_outputs,
svga->curr.tes->base.info.num_inputs,
svga->curr.vs->base.info.output_semantic_name,
svga->curr.vs->base.info.output_semantic_index,
svga->curr.tes->base.info.input_semantic_name,
svga->curr.tes->base.info.input_semantic_index,
svga->curr.vertices_per_patch);
svga->pipe.bind_tcs_state(&svga->pipe, new_tcs);
svga->tcs.passthrough_tcs = new_tcs;
svga->tcs.vs = svga->curr.vs;
svga->tcs.tes = svga->curr.tes;
svga->tcs.vertices_per_patch = svga->curr.vertices_per_patch;
}
struct pipe_constant_buffer cb;
cb.buffer = NULL;
cb.user_buffer = (void *) svga->curr.default_tesslevels;
cb.buffer_offset = 0;
cb.buffer_size = 2 * 4 * sizeof(float);
svga->pipe.set_constant_buffer(&svga->pipe, PIPE_SHADER_TESS_CTRL, 0, &cb);
}
static enum pipe_error
emit_hw_tes(struct svga_context *svga, uint64_t dirty)
{
struct svga_shader_variant *variant;
struct svga_tes_shader *tes = svga->curr.tes;
enum pipe_error ret = PIPE_OK;
struct svga_compile_key key;
assert(svga_have_sm5(svga));
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_EMITTES);
if (!tes) {
/* The GL spec implies that TES is optional when there's a TCS,
* but that's apparently a spec error. Assert if we have a TCS
* but no TES.
*/
assert(!svga->curr.tcs);
if (svga->state.hw_draw.tes != NULL) {
/** The previous tessellation evaluation shader is made inactive.
* Needs to unbind the tessellation evaluation shader.
*/
ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_DS, NULL);
if (ret != PIPE_OK)
goto done;
svga->state.hw_draw.tes = NULL;
}
goto done;
}
if (!svga->curr.tcs) {
/* TES state is processed before the TCS
* shader and that's why we're checking for and creating the
* passthough TCS in the emit_hw_tes() function.
*/
get_passthrough_tcs(svga);
svga->tcs.passthrough = TRUE;
}
else {
svga->tcs.passthrough = FALSE;
}
make_tes_key(svga, &key);
/* See if we already have a TES variant that matches the key */
variant = svga_search_shader_key(&tes->base, &key);
if (!variant) {
ret = compile_tes(svga, tes, &key, &variant);
if (ret != PIPE_OK)
goto done;
/* insert the new variant at head of linked list */
assert(variant);
variant->next = tes->base.variants;
tes->base.variants = variant;
}
if (variant != svga->state.hw_draw.tes) {
/* Bind the new variant */
ret = svga_set_shader(svga, SVGA3D_SHADERTYPE_DS, variant);
if (ret != PIPE_OK)
goto done;
svga->rebind.flags.tes = FALSE;
svga->dirty |= SVGA_NEW_TES_VARIANT;
svga->state.hw_draw.tes = variant;
}
done:
SVGA_STATS_TIME_POP(svga_sws(svga));
return ret;
}
struct svga_tracked_state svga_hw_tes =
{
"tessellation evaluation shader (hwtnl)",
/* TBD SVGA_NEW_VS/SVGA_NEW_FS/SVGA_NEW_GS are required or not*/
(SVGA_NEW_VS |
SVGA_NEW_FS |
SVGA_NEW_GS |
SVGA_NEW_TCS |
SVGA_NEW_TES |
SVGA_NEW_TEXTURE_BINDING |
SVGA_NEW_SAMPLER |
SVGA_NEW_RAST),
emit_hw_tes
};

View File

@ -139,7 +139,7 @@ emit_tex_binding_unit(struct svga_context *svga,
static enum pipe_error static enum pipe_error
update_tss_binding(struct svga_context *svga, unsigned dirty) update_tss_binding(struct svga_context *svga, uint64_t dirty )
{ {
const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT; const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
boolean reemit = svga->rebind.flags.texture_samplers; boolean reemit = svga->rebind.flags.texture_samplers;
@ -149,8 +149,7 @@ update_tss_binding(struct svga_context *svga, unsigned dirty)
struct bind_queue queue; struct bind_queue queue;
if (svga_have_vgpu10(svga)) assert(!svga_have_vgpu10(svga));
return PIPE_OK;
queue.bind_count = 0; queue.bind_count = 0;
@ -167,7 +166,8 @@ update_tss_binding(struct svga_context *svga, unsigned dirty)
/* Polygon stipple */ /* Polygon stipple */
if (svga->curr.rast->templ.poly_stipple_enable) { if (svga->curr.rast->templ.poly_stipple_enable) {
const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit; const unsigned unit =
svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
emit_tex_binding_unit(svga, unit, emit_tex_binding_unit(svga, unit,
svga->polygon_stipple.sampler, svga->polygon_stipple.sampler,
&svga->polygon_stipple.sampler_view->base, &svga->polygon_stipple.sampler_view->base,
@ -257,7 +257,8 @@ svga_reemit_tss_bindings(struct svga_context *svga)
/* Polygon stipple */ /* Polygon stipple */
if (svga->curr.rast && svga->curr.rast->templ.poly_stipple_enable) { if (svga->curr.rast && svga->curr.rast->templ.poly_stipple_enable) {
const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit; const unsigned unit =
svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
struct svga_hw_view_state *view = &svga->state.hw_draw.views[unit]; struct svga_hw_view_state *view = &svga->state.hw_draw.views[unit];
if (view->v) { if (view->v) {
@ -380,14 +381,13 @@ emit_tss_unit(struct svga_context *svga, unsigned unit,
} }
static enum pipe_error static enum pipe_error
update_tss(struct svga_context *svga, unsigned dirty) update_tss(struct svga_context *svga, uint64_t dirty )
{ {
const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT; const enum pipe_shader_type shader = PIPE_SHADER_FRAGMENT;
unsigned i; unsigned i;
struct ts_queue queue; struct ts_queue queue;
if (svga_have_vgpu10(svga)) assert(!svga_have_vgpu10(svga));
return PIPE_OK;
queue.ts_count = 0; queue.ts_count = 0;
for (i = 0; i < svga->curr.num_samplers[shader]; i++) { for (i = 0; i < svga->curr.num_samplers[shader]; i++) {
@ -400,7 +400,7 @@ update_tss(struct svga_context *svga, unsigned dirty)
/* polygon stipple sampler */ /* polygon stipple sampler */
if (svga->curr.rast->templ.poly_stipple_enable) { if (svga->curr.rast->templ.poly_stipple_enable) {
emit_tss_unit(svga, emit_tss_unit(svga,
svga->state.hw_draw.fs->pstipple_sampler_unit, svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit,
svga->polygon_stipple.sampler, svga->polygon_stipple.sampler,
&queue); &queue);
} }

View File

@ -40,7 +40,7 @@
static enum pipe_error static enum pipe_error
emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty) emit_hw_vs_vdecl(struct svga_context *svga, uint64_t dirty)
{ {
const struct pipe_vertex_element *ve = svga->curr.velems->velem; const struct pipe_vertex_element *ve = svga->curr.velems->velem;
SVGA3dVertexDecl decls[SVGA3D_INPUTREG_MAX]; SVGA3dVertexDecl decls[SVGA3D_INPUTREG_MAX];
@ -136,7 +136,7 @@ emit_hw_vs_vdecl(struct svga_context *svga, unsigned dirty)
static enum pipe_error static enum pipe_error
emit_hw_vdecl(struct svga_context *svga, unsigned dirty) emit_hw_vdecl(struct svga_context *svga, uint64_t dirty)
{ {
/* SVGA_NEW_NEED_SWTNL /* SVGA_NEW_NEED_SWTNL
*/ */

View File

@ -164,7 +164,7 @@ compile_vs(struct svga_context *svga,
static void static void
make_vs_key(struct svga_context *svga, struct svga_compile_key *key) make_vs_key(struct svga_context *svga, struct svga_compile_key *key)
{ {
const enum pipe_shader_type shader = PIPE_SHADER_VERTEX; struct svga_vertex_shader *vs = svga->curr.vs;
memset(key, 0, sizeof *key); memset(key, 0, sizeof *key);
@ -176,7 +176,8 @@ make_vs_key(struct svga_context *svga, struct svga_compile_key *key)
} }
/* SVGA_NEW_PRESCALE */ /* SVGA_NEW_PRESCALE */
key->vs.need_prescale = svga->state.hw_clear.prescale.enabled && key->vs.need_prescale = svga->state.hw_clear.prescale[0].enabled &&
(svga->curr.tes == NULL) &&
(svga->curr.gs == NULL); (svga->curr.gs == NULL);
/* SVGA_NEW_RAST */ /* SVGA_NEW_RAST */
@ -199,10 +200,16 @@ make_vs_key(struct svga_context *svga, struct svga_compile_key *key)
key->vs.attrib_puint_to_sscaled = svga->curr.velems->attrib_puint_to_sscaled; key->vs.attrib_puint_to_sscaled = svga->curr.velems->attrib_puint_to_sscaled;
/* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER */ /* SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER */
svga_init_shader_key_common(svga, shader, key); svga_init_shader_key_common(svga, PIPE_SHADER_VERTEX, &vs->base, key);
/* SVGA_NEW_RAST */ /* SVGA_NEW_RAST */
key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable; key->clip_plane_enable = svga->curr.rast->templ.clip_plane_enable;
/* Determine if this shader is the last shader in the vertex
* processing stage.
*/
key->last_vertex_stage = !(svga->curr.gs ||
svga->curr.tcs || svga->curr.tes);
} }
@ -338,7 +345,7 @@ compile_passthrough_vs(struct svga_context *svga,
static enum pipe_error static enum pipe_error
emit_hw_vs(struct svga_context *svga, unsigned dirty) emit_hw_vs(struct svga_context *svga, uint64_t dirty)
{ {
struct svga_shader_variant *variant; struct svga_shader_variant *variant;
struct svga_vertex_shader *vs = svga->curr.vs; struct svga_vertex_shader *vs = svga->curr.vs;

View File

@ -32,6 +32,9 @@ struct svga_stream_output {
struct pipe_stream_output_info info; struct pipe_stream_output_info info;
unsigned pos_out_index; // position output index unsigned pos_out_index; // position output index
unsigned id; unsigned id;
unsigned streammask; // bitmask to specify which streams are enabled
unsigned buffer_stream;
struct svga_winsys_buffer *declBuf;
}; };
struct svga_stream_output * struct svga_stream_output *
@ -50,4 +53,20 @@ svga_delete_stream_output(struct svga_context *svga,
enum pipe_error enum pipe_error
svga_rebind_stream_output_targets(struct svga_context *svga); svga_rebind_stream_output_targets(struct svga_context *svga);
void
svga_create_stream_output_queries(struct svga_context *svga);
void
svga_destroy_stream_output_queries(struct svga_context *svga);
void
svga_begin_stream_output_queries(struct svga_context *svga, unsigned mask);
void
svga_end_stream_output_queries(struct svga_context *svga, unsigned mask);
unsigned
svga_get_primcount_from_stream_output(struct svga_context *svga,
unsigned stream);
#endif /* SVGA_STREAMOUT_H */ #endif /* SVGA_STREAMOUT_H */

View File

@ -578,6 +578,16 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
} }
} }
/**
* Create an alternate surface view for the specified context if the
* view was created for another context.
*/
if (s && s->base.context != &svga->pipe) {
struct pipe_surface *surf;
surf = svga_create_surface_view(&svga->pipe, s->base.texture, &s->base, FALSE);
s = svga_surface(surf);
}
if (s && s->view_id == SVGA3D_INVALID_ID) { if (s && s->view_id == SVGA3D_INVALID_ID) {
SVGA3dResourceType resType; SVGA3dResourceType resType;
SVGA3dRenderTargetViewDesc desc; SVGA3dRenderTargetViewDesc desc;

View File

@ -146,6 +146,8 @@ static inline SVGA3dResourceType
svga_resource_type(enum pipe_texture_target target) svga_resource_type(enum pipe_texture_target target)
{ {
switch (target) { switch (target) {
case PIPE_BUFFER:
return SVGA3D_RESOURCE_BUFFER;
case PIPE_TEXTURE_1D: case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_1D_ARRAY: case PIPE_TEXTURE_1D_ARRAY:
return SVGA3D_RESOURCE_TEXTURE1D; return SVGA3D_RESOURCE_TEXTURE1D;

View File

@ -90,11 +90,12 @@ svga_vbuf_render_allocate_vertices(struct vbuf_render *render,
if (!svga_render->vbuf) { if (!svga_render->vbuf) {
svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size); svga_render->vbuf_size = MAX2(size, svga_render->vbuf_alloc_size);
svga_render->vbuf = pipe_buffer_create(screen, svga_render->vbuf = SVGA_TRY_PTR(pipe_buffer_create
PIPE_BIND_VERTEX_BUFFER, (screen, PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM, PIPE_USAGE_STREAM,
svga_render->vbuf_size); svga_render->vbuf_size));
if (!svga_render->vbuf) { if (!svga_render->vbuf) {
svga_retry_enter(svga);
svga_context_flush(svga, NULL); svga_context_flush(svga, NULL);
assert(!svga_render->vbuf); assert(!svga_render->vbuf);
svga_render->vbuf = pipe_buffer_create(screen, svga_render->vbuf = pipe_buffer_create(screen,
@ -104,6 +105,7 @@ svga_vbuf_render_allocate_vertices(struct vbuf_render *render,
/* The buffer allocation may fail if we run out of memory. /* The buffer allocation may fail if we run out of memory.
* The draw module's vbuf code should handle that without crashing. * The draw module's vbuf code should handle that without crashing.
*/ */
svga_retry_exit(svga);
} }
svga->swtnl.new_vdecl = TRUE; svga->swtnl.new_vdecl = TRUE;
@ -267,7 +269,7 @@ svga_vbuf_submit_state(struct svga_vbuf_render *svga_render)
else { else {
svga_hwtnl_set_flatshade(svga->hwtnl, svga_hwtnl_set_flatshade(svga->hwtnl,
svga->curr.rast->templ.flatshade || svga->curr.rast->templ.flatshade ||
svga->state.hw_draw.fs->uses_flat_interp, svga_is_using_flat_shading(svga),
svga->curr.rast->templ.flatshade_first); svga->curr.rast->templ.flatshade_first);
svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode); svga_hwtnl_set_fillmode(svga->hwtnl, svga->curr.rast->hw_fillmode);
@ -286,10 +288,10 @@ svga_vbuf_render_draw_arrays(struct vbuf_render *render,
struct svga_context *svga = svga_render->svga; struct svga_context *svga = svga_render->svga;
unsigned bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) unsigned bias = (svga_render->vbuf_offset - svga_render->vdecl_offset)
/ svga_render->vertex_size; / svga_render->vertex_size;
enum pipe_error ret = PIPE_OK;
/* instancing will already have been resolved at this point by 'draw' */ /* instancing will already have been resolved at this point by 'draw' */
const unsigned start_instance = 0; const unsigned start_instance = 0;
const unsigned instance_count = 1; const unsigned instance_count = 1;
boolean retried;
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_VBUFDRAWARRAYS); SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_VBUFDRAWARRAYS);
@ -301,17 +303,13 @@ svga_vbuf_render_draw_arrays(struct vbuf_render *render,
* redbook/polys.c * redbook/polys.c
*/ */
svga_update_state_retry(svga, SVGA_STATE_HW_DRAW); svga_update_state_retry(svga, SVGA_STATE_HW_DRAW);
SVGA_RETRY_CHECK(svga, svga_hwtnl_draw_arrays
ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, (svga->hwtnl, svga_render->prim, start + bias,
nr, start_instance, instance_count); nr, start_instance, instance_count, 0), retried);
if (ret != PIPE_OK) { if (retried) {
svga_context_flush(svga, NULL);
ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim,
start + bias, nr,
start_instance, instance_count);
svga->swtnl.new_vbuf = TRUE; svga->swtnl.new_vbuf = TRUE;
assert(ret == PIPE_OK);
} }
SVGA_STATS_TIME_POP(svga_sws(svga)); SVGA_STATS_TIME_POP(svga_sws(svga));
} }
@ -325,7 +323,7 @@ svga_vbuf_render_draw_elements(struct vbuf_render *render,
struct svga_context *svga = svga_render->svga; struct svga_context *svga = svga_render->svga;
int bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) int bias = (svga_render->vbuf_offset - svga_render->vdecl_offset)
/ svga_render->vertex_size; / svga_render->vertex_size;
boolean ret; boolean retried;
/* instancing will already have been resolved at this point by 'draw' */ /* instancing will already have been resolved at this point by 'draw' */
const struct pipe_draw_info info = { const struct pipe_draw_info info = {
.index_size = 2, .index_size = 2,
@ -354,13 +352,12 @@ svga_vbuf_render_draw_elements(struct vbuf_render *render,
* redbook/polys.c * redbook/polys.c
*/ */
svga_update_state_retry(svga, SVGA_STATE_HW_DRAW); svga_update_state_retry(svga, SVGA_STATE_HW_DRAW);
ret = svga_hwtnl_draw_range_elements(svga->hwtnl, &info, nr_indices); SVGA_RETRY_CHECK(svga, svga_hwtnl_draw_range_elements(svga->hwtnl, &info,
if (ret != PIPE_OK) { nr_indices), retried);
svga_context_flush(svga, NULL); if (retried) {
ret = svga_hwtnl_draw_range_elements(svga->hwtnl, &info, nr_indices);
svga->swtnl.new_vbuf = TRUE; svga->swtnl.new_vbuf = TRUE;
assert(ret == PIPE_OK);
} }
SVGA_STATS_TIME_POP(svga_sws(svga)); SVGA_STATS_TIME_POP(svga_sws(svga));
} }

View File

@ -51,7 +51,7 @@
static void static void
set_draw_viewport(struct svga_context *svga) set_draw_viewport(struct svga_context *svga)
{ {
struct pipe_viewport_state vp = svga->curr.viewport; struct pipe_viewport_state vp = svga->curr.viewport[0];
float adjx = 0.0f; float adjx = 0.0f;
float adjy = 0.0f; float adjy = 0.0f;
@ -98,7 +98,7 @@ set_draw_viewport(struct svga_context *svga)
} }
static enum pipe_error static enum pipe_error
update_swtnl_draw(struct svga_context *svga, unsigned dirty) update_swtnl_draw(struct svga_context *svga, uint64_t dirty)
{ {
SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_SWTNLUPDATEDRAW); SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_SWTNLUPDATEDRAW);
@ -191,7 +191,6 @@ svga_vdecl_to_input_element(struct svga_context *svga,
{ {
SVGA3dElementLayoutId id; SVGA3dElementLayoutId id;
SVGA3dInputElementDesc elements[PIPE_MAX_ATTRIBS]; SVGA3dInputElementDesc elements[PIPE_MAX_ATTRIBS];
enum pipe_error ret;
unsigned i; unsigned i;
assert(num_decls <= PIPE_MAX_ATTRIBS); assert(num_decls <= PIPE_MAX_ATTRIBS);
@ -208,13 +207,8 @@ svga_vdecl_to_input_element(struct svga_context *svga,
id = util_bitmask_add(svga->input_element_object_id_bm); id = util_bitmask_add(svga->input_element_object_id_bm);
ret = SVGA3D_vgpu10_DefineElementLayout(svga->swc, num_decls, id, elements); SVGA_RETRY(svga, SVGA3D_vgpu10_DefineElementLayout(svga->swc, num_decls, id,
if (ret != PIPE_OK) { elements));
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_DefineElementLayout(svga->swc, num_decls,
id, elements);
assert(ret == PIPE_OK);
}
return id; return id;
} }
@ -306,22 +300,14 @@ svga_swtnl_update_vdecl(struct svga_context *svga)
any_change = memcmp(svga_render->vdecl, vdecl, sizeof(vdecl)); any_change = memcmp(svga_render->vdecl, vdecl, sizeof(vdecl));
if (svga_have_vgpu10(svga)) { if (svga_have_vgpu10(svga)) {
enum pipe_error ret;
if (!any_change && svga_render->layout_id != SVGA3D_INVALID_ID) { if (!any_change && svga_render->layout_id != SVGA3D_INVALID_ID) {
goto done; goto done;
} }
if (svga_render->layout_id != SVGA3D_INVALID_ID) { if (svga_render->layout_id != SVGA3D_INVALID_ID) {
/* destroy old */ /* destroy old */
ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc, SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyElementLayout
svga_render->layout_id); (svga->swc, svga_render->layout_id));
if (ret != PIPE_OK) {
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_DestroyElementLayout(svga->swc,
svga_render->layout_id);
assert(ret == PIPE_OK);
}
/** /**
* reset current layout id state after the element layout is * reset current layout id state after the element layout is
@ -340,14 +326,8 @@ svga_swtnl_update_vdecl(struct svga_context *svga)
/* bind new */ /* bind new */
if (svga->state.hw_draw.layout_id != svga_render->layout_id) { if (svga->state.hw_draw.layout_id != svga_render->layout_id) {
ret = SVGA3D_vgpu10_SetInputLayout(svga->swc, svga_render->layout_id); SVGA_RETRY(svga, SVGA3D_vgpu10_SetInputLayout(svga->swc,
if (ret != PIPE_OK) { svga_render->layout_id));
svga_context_flush(svga, NULL);
ret = SVGA3D_vgpu10_SetInputLayout(svga->swc,
svga_render->layout_id);
assert(ret == PIPE_OK);
}
svga->state.hw_draw.layout_id = svga_render->layout_id; svga->state.hw_draw.layout_id = svga_render->layout_id;
} }
} }
@ -366,7 +346,7 @@ done:
static enum pipe_error static enum pipe_error
update_swtnl_vdecl(struct svga_context *svga, unsigned dirty) update_swtnl_vdecl(struct svga_context *svga, uint64_t dirty)
{ {
return svga_swtnl_update_vdecl(svga); return svga_swtnl_update_vdecl(svga);
} }

View File

@ -238,14 +238,18 @@ svga_tgsi_vgpu9_translate(struct svga_context *svga,
memcpy(&variant->key, key, sizeof(*key)); memcpy(&variant->key, key, sizeof(*key));
variant->id = UTIL_BITMASK_INVALID_INDEX; variant->id = UTIL_BITMASK_INVALID_INDEX;
variant->pstipple_sampler_unit = emit.pstipple_sampler_unit; if (unit == PIPE_SHADER_FRAGMENT) {
struct svga_fs_variant *fs_variant = svga_fs_variant(variant);
fs_variant->pstipple_sampler_unit = emit.pstipple_sampler_unit;
/* If there was exactly one write to a fragment shader output register /* If there was exactly one write to a fragment shader output register
* and it came from a constant buffer, we know all fragments will have * and it came from a constant buffer, we know all fragments will have
* the same color (except for blending). * the same color (except for blending).
*/ */
variant->constant_color_output = fs_variant->constant_color_output =
emit.constant_color_output && emit.num_output_writes == 1; emit.constant_color_output && emit.num_output_writes == 1;
}
#if 0 #if 0
if (!svga_shader_verify(variant->tokens, variant->nr_tokens) || if (!svga_shader_verify(variant->tokens, variant->nr_tokens) ||

View File

@ -30,7 +30,7 @@
#include "svga3d_reg.h" #include "svga3d_reg.h"
#define MAX_VGPU10_ADDR_REGS 2 #define MAX_VGPU10_ADDR_REGS 4
struct svga_compile_key; struct svga_compile_key;
struct svga_context; struct svga_context;

File diff suppressed because it is too large Load Diff

View File

@ -427,7 +427,9 @@ struct svga_winsys_context
uint32 shaderId, uint32 shaderId,
SVGA3dShaderType shaderType, SVGA3dShaderType shaderType,
const uint32 *bytecode, const uint32 *bytecode,
uint32 bytecodeLen); uint32 bytecodeLen,
const SVGA3dDXShaderSignatureHeader *sgnInfo,
uint32 sgnLen);
/** /**
* Destroy a DX GB shader. * Destroy a DX GB shader.
@ -457,7 +459,13 @@ struct svga_winsys_context
/** For HUD queries */ /** For HUD queries */
uint64_t num_commands; uint64_t num_commands;
uint64_t num_command_buffers;
uint64_t num_draw_commands; uint64_t num_draw_commands;
uint64_t num_shader_reloc;
uint64_t num_surf_reloc;
/* Whether we are in retry processing */
unsigned int in_retry;
}; };

View File

@ -65,6 +65,7 @@
#define VMW_MAX_SURF_MEM_FACTOR 2 #define VMW_MAX_SURF_MEM_FACTOR 2
struct vmw_buffer_relocation struct vmw_buffer_relocation
{ {
struct pb_buffer *buffer; struct pb_buffer *buffer;
@ -701,20 +702,19 @@ vmw_svga_winsys_vgpu10_shader_create(struct svga_winsys_context *swc,
uint32 shaderId, uint32 shaderId,
SVGA3dShaderType shaderType, SVGA3dShaderType shaderType,
const uint32 *bytecode, const uint32 *bytecode,
uint32 bytecodeLen) uint32 bytecodeLen,
const SVGA3dDXShaderSignatureHeader *sgnInfo,
uint32 sgnLen)
{ {
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc); struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
struct vmw_svga_winsys_shader *shader; struct vmw_svga_winsys_shader *shader;
struct svga_winsys_gb_shader *gb_shader = shader = vmw_svga_shader_create(&vswc->vws->base, shaderType, bytecode,
vmw_svga_winsys_shader_create(&vswc->vws->base, shaderType, bytecode, bytecodeLen, sgnInfo, sgnLen);
bytecodeLen); if (!shader)
if (!gb_shader)
return NULL; return NULL;
shader = vmw_svga_winsys_shader(gb_shader);
shader->shid = shaderId; shader->shid = shaderId;
return svga_winsys_shader(shader);
return gb_shader;
} }
/** /**

View File

@ -28,7 +28,9 @@
#include "util/u_debug.h" #include "util/u_debug.h"
#include "util/u_memory.h" #include "util/u_memory.h"
#include "vmw_context.h"
#include "vmw_shader.h" #include "vmw_shader.h"
#include "vmw_buffer.h"
#include "vmw_screen.h" #include "vmw_screen.h"
void void
@ -63,3 +65,54 @@ vmw_svga_winsys_shader_reference(struct vmw_svga_winsys_shader **pdst,
*pdst = src; *pdst = src;
} }
/**
* A helper function to create a shader object and upload the
* shader bytecode and signature if specified to the shader memory.
*/
struct vmw_svga_winsys_shader *
vmw_svga_shader_create(struct svga_winsys_screen *sws,
SVGA3dShaderType type,
const uint32 *bytecode,
uint32 bytecodeLen,
const SVGA3dDXShaderSignatureHeader *sgnInfo,
uint32 sgnLen)
{
struct vmw_svga_winsys_shader *shader;
void *map;
shader = CALLOC_STRUCT(vmw_svga_winsys_shader);
if (!shader)
return NULL;
pipe_reference_init(&shader->refcnt, 1);
p_atomic_set(&shader->validated, 0);
shader->screen = vmw_winsys_screen(sws);
shader->buf = sws->buffer_create(sws, 64,
SVGA_BUFFER_USAGE_SHADER,
bytecodeLen + sgnLen);
if (!shader->buf) {
FREE(shader);
return NULL;
}
map = sws->buffer_map(sws, shader->buf, PIPE_TRANSFER_WRITE);
if (!map) {
FREE(shader);
return NULL;
}
/* copy the shader bytecode */
memcpy(map, bytecode, bytecodeLen);
/* if shader signature is specified, append it to the bytecode. */
if (sgnLen) {
assert(sws->have_sm5);
map = (char *)map + bytecodeLen;
memcpy(map, sgnInfo, sgnLen);
}
sws->buffer_unmap(sws, shader->buf);
return shader;
}

View File

@ -65,4 +65,12 @@ void
vmw_svga_winsys_shader_reference(struct vmw_svga_winsys_shader **pdst, vmw_svga_winsys_shader_reference(struct vmw_svga_winsys_shader **pdst,
struct vmw_svga_winsys_shader *src); struct vmw_svga_winsys_shader *src);
struct vmw_svga_winsys_shader *
vmw_svga_shader_create(struct svga_winsys_screen *sws,
SVGA3dShaderType type,
const uint32 *bytecode,
uint32 bytecodeLen,
const SVGA3dDXShaderSignatureHeader *sgnInfo,
uint32 sgnLen);
#endif /* VMW_SHADER_H_ */ #endif /* VMW_SHADER_H_ */