summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/svga/drm/vmw_context.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/svga/drm/vmw_context.c')
-rw-r--r--src/gallium/winsys/svga/drm/vmw_context.c206
1 files changed, 167 insertions, 39 deletions
diff --git a/src/gallium/winsys/svga/drm/vmw_context.c b/src/gallium/winsys/svga/drm/vmw_context.c
index 31bedde7c41..394795eae14 100644
--- a/src/gallium/winsys/svga/drm/vmw_context.c
+++ b/src/gallium/winsys/svga/drm/vmw_context.c
@@ -1,5 +1,5 @@
/**********************************************************
- * Copyright 2009 VMware, Inc. All rights reserved.
+ * Copyright 2009-2015 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
@@ -41,6 +41,7 @@
#include "vmw_surface.h"
#include "vmw_fence.h"
#include "vmw_shader.h"
+#include "vmw_query.h"
#define VMW_COMMAND_SIZE (64*1024)
#define VMW_SURFACE_RELOCS (1024)
@@ -391,24 +392,27 @@ vmw_swc_mob_relocation(struct svga_winsys_context *swc,
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
struct vmw_buffer_relocation *reloc;
+ struct pb_buffer *pb_buffer = vmw_pb_buffer(buffer);
- assert(vswc->region.staged < vswc->region.reserved);
+ if (id) {
+ assert(vswc->region.staged < vswc->region.reserved);
- reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];
- reloc->mob.id = id;
- reloc->mob.offset_into_mob = offset_into_mob;
+ reloc = &vswc->region.relocs[vswc->region.used + vswc->region.staged];
+ reloc->mob.id = id;
+ reloc->mob.offset_into_mob = offset_into_mob;
- /*
- * pb_validate holds a refcount to the buffer, so no need to
- * refcount it again in the relocation.
- */
- reloc->buffer = vmw_pb_buffer(buffer);
- reloc->offset = offset;
- reloc->is_mob = TRUE;
- ++vswc->region.staged;
+ /*
+ * pb_validate holds a refcount to the buffer, so no need to
+ * refcount it again in the relocation.
+ */
+ reloc->buffer = pb_buffer;
+ reloc->offset = offset;
+ reloc->is_mob = TRUE;
+ ++vswc->region.staged;
+ }
- if (vmw_swc_add_validate_buffer(vswc, reloc->buffer, flags)) {
- vswc->seen_mobs += reloc->buffer->size;
+ if (vmw_swc_add_validate_buffer(vswc, pb_buffer, flags)) {
+ vswc->seen_mobs += pb_buffer->size;
/* divide by 5, tested for best performance */
if (vswc->seen_mobs >= vswc->vws->ioctl.max_mob_memory / VMW_MAX_MOB_MEM_FACTOR)
vswc->preemptive_flush = TRUE;
@@ -481,7 +485,8 @@ vmw_swc_surface_only_relocation(struct svga_winsys_context *swc,
p_atomic_inc(&vsurf->validated);
}
- *where = vsurf->sid;
+ if (where)
+ *where = vsurf->sid;
}
static void
@@ -495,7 +500,7 @@ vmw_swc_surface_relocation(struct svga_winsys_context *swc,
assert(swc->have_gb_objects || mobid == NULL);
- if(!surface) {
+ if (!surface) {
*where = SVGA3D_INVALID_ID;
if (mobid)
*mobid = SVGA3D_INVALID_ID;
@@ -525,51 +530,68 @@ vmw_swc_shader_relocation(struct svga_winsys_context *swc,
uint32 *shid,
uint32 *mobid,
uint32 *offset,
- struct svga_winsys_gb_shader *shader)
+ struct svga_winsys_gb_shader *shader,
+ unsigned flags)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ struct vmw_winsys_screen *vws = vswc->vws;
struct vmw_svga_winsys_shader *vshader;
struct vmw_ctx_validate_item *ishader;
+
if(!shader) {
*shid = SVGA3D_INVALID_ID;
return;
}
- assert(vswc->shader.staged < vswc->shader.reserved);
vshader = vmw_svga_winsys_shader(shader);
- ishader = util_hash_table_get(vswc->hash, vshader);
- if (ishader == NULL) {
- ishader = &vswc->shader.items[vswc->shader.used + vswc->shader.staged];
- vmw_svga_winsys_shader_reference(&ishader->vshader, vshader);
- ishader->referenced = FALSE;
- /*
- * Note that a failure here may just fall back to unhashed behavior
- * and potentially cause unnecessary flushing, so ignore the
- * return code.
- */
- (void) util_hash_table_set(vswc->hash, vshader, ishader);
- ++vswc->shader.staged;
- }
+ if (!vws->base.have_vgpu10) {
+ assert(vswc->shader.staged < vswc->shader.reserved);
+ ishader = util_hash_table_get(vswc->hash, vshader);
+
+ if (ishader == NULL) {
+ ishader = &vswc->shader.items[vswc->shader.used + vswc->shader.staged];
+ vmw_svga_winsys_shader_reference(&ishader->vshader, vshader);
+ ishader->referenced = FALSE;
+ /*
+ * Note that a failure here may just fall back to unhashed behavior
+ * and potentially cause unnecessary flushing, so ignore the
+ * return code.
+ */
+ (void) util_hash_table_set(vswc->hash, vshader, ishader);
+ ++vswc->shader.staged;
+ }
- if (!ishader->referenced) {
- ishader->referenced = TRUE;
- p_atomic_inc(&vshader->validated);
+ if (!ishader->referenced) {
+ ishader->referenced = TRUE;
+ p_atomic_inc(&vshader->validated);
+ }
}
- *shid = vshader->shid;
+ if (shid)
+ *shid = vshader->shid;
- if (mobid != NULL && vshader->buf)
+ if (vshader->buf)
vmw_swc_mob_relocation(swc, mobid, offset, vshader->buf,
0, SVGA_RELOC_READ);
}
static void
+vmw_swc_query_relocation(struct svga_winsys_context *swc,
+ SVGAMobId *id,
+ struct svga_winsys_gb_query *query)
+{
+ /* Queries are backed by one big MOB */
+ vmw_swc_mob_relocation(swc, id, NULL, query->buf, 0,
+ SVGA_RELOC_READ | SVGA_RELOC_WRITE);
+}
+
+static void
vmw_swc_commit(struct svga_winsys_context *swc)
{
struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
- assert(vswc->command.reserved);
+ assert(vswc->command.reserved >= 0);
assert(vswc->command.used + vswc->command.reserved <= vswc->command.size);
vswc->command.used += vswc->command.reserved;
vswc->command.reserved = 0;
@@ -633,6 +655,96 @@ static int vmw_ptr_compare(void *key1, void *key2)
return (key1 == key2) ? 0 : 1;
}
+
+/**
+ * vmw_svga_winsys_vgpu10_shader_screate - The winsys shader_crate callback
+ *
+ * @swc: The winsys context.
+ * @shaderId: Previously allocated shader id.
+ * @shaderType: The shader type.
+ * @bytecode: The shader bytecode
+ * @bytecodelen: The length of the bytecode.
+ *
+ * Creates an svga_winsys_gb_shader structure and allocates a buffer for the
+ * shader code and copies the shader code into the buffer. Shader
+ * resource creation is not done.
+ */
+static struct svga_winsys_gb_shader *
+vmw_svga_winsys_vgpu10_shader_create(struct svga_winsys_context *swc,
+ uint32 shaderId,
+ SVGA3dShaderType shaderType,
+ const uint32 *bytecode,
+ uint32 bytecodeLen)
+{
+ struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+ struct vmw_svga_winsys_shader *shader;
+ struct svga_winsys_gb_shader *gb_shader =
+ vmw_svga_winsys_shader_create(&vswc->vws->base, shaderType, bytecode,
+ bytecodeLen);
+ if (!gb_shader)
+ return NULL;
+
+ shader = vmw_svga_winsys_shader(gb_shader);
+ shader->shid = shaderId;
+
+ return gb_shader;
+}
+
+/**
+ * vmw_svga_winsys_vgpu10_shader_destroy - The winsys shader_destroy callback.
+ *
+ * @swc: The winsys context.
+ * @shader: A shader structure previously allocated by shader_create.
+ *
+ * Frees the shader structure and the buffer holding the shader code.
+ */
+static void
+vmw_svga_winsys_vgpu10_shader_destroy(struct svga_winsys_context *swc,
+ struct svga_winsys_gb_shader *shader)
+{
+ struct vmw_svga_winsys_context *vswc = vmw_svga_winsys_context(swc);
+
+ vmw_svga_winsys_shader_destroy(&vswc->vws->base, shader);
+}
+
+/**
+ * vmw_svga_winsys_resource_rebind - The winsys resource_rebind callback
+ *
+ * @swc: The winsys context.
+ * @surface: The surface to be referenced.
+ * @shader: The shader to be referenced.
+ * @flags: Relocation flags.
+ *
+ * This callback is needed because shader backing buffers are sub-allocated, and
+ * hence the kernel fencing is not sufficient. The buffers need to be put on
+ * the context's validation list and fenced after command submission to avoid
+ * reuse of busy shader buffers. In addition, surfaces need to be put on the
+ * validation list in order for the driver to regard them as referenced
+ * by the command stream.
+ */
+static enum pipe_error
+vmw_svga_winsys_resource_rebind(struct svga_winsys_context *swc,
+ struct svga_winsys_surface *surface,
+ struct svga_winsys_gb_shader *shader,
+ unsigned flags)
+{
+ /**
+ * Need to reserve one validation item for either the surface or
+ * the shader.
+ */
+ if (!vmw_swc_reserve(swc, 0, 1))
+ return PIPE_ERROR_OUT_OF_MEMORY;
+
+ if (surface)
+ vmw_swc_surface_relocation(swc, NULL, NULL, surface, flags);
+ else if (shader)
+ vmw_swc_shader_relocation(swc, NULL, NULL, NULL, shader, flags);
+
+ vmw_swc_commit(swc);
+
+ return PIPE_OK;
+}
+
struct svga_winsys_context *
vmw_svga_winsys_context_create(struct svga_winsys_screen *sws)
{
@@ -648,6 +760,8 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws)
vswc->base.surface_relocation = vmw_swc_surface_relocation;
vswc->base.region_relocation = vmw_swc_region_relocation;
vswc->base.mob_relocation = vmw_swc_mob_relocation;
+ vswc->base.query_relocation = vmw_swc_query_relocation;
+ vswc->base.query_bind = vmw_swc_query_bind;
vswc->base.context_relocation = vmw_swc_context_relocation;
vswc->base.shader_relocation = vmw_swc_shader_relocation;
vswc->base.commit = vmw_swc_commit;
@@ -655,7 +769,19 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws)
vswc->base.surface_map = vmw_svga_winsys_surface_map;
vswc->base.surface_unmap = vmw_svga_winsys_surface_unmap;
- vswc->base.cid = vmw_ioctl_context_create(vws);
+ vswc->base.shader_create = vmw_svga_winsys_vgpu10_shader_create;
+ vswc->base.shader_destroy = vmw_svga_winsys_vgpu10_shader_destroy;
+
+ vswc->base.resource_rebind = vmw_svga_winsys_resource_rebind;
+
+ if (sws->have_vgpu10)
+ vswc->base.cid = vmw_ioctl_extended_context_create(vws, sws->have_vgpu10);
+ else
+ vswc->base.cid = vmw_ioctl_context_create(vws);
+
+ if (vswc->base.cid == -1)
+ goto out_no_context;
+
vswc->base.have_gb_objects = sws->have_gb_objects;
vswc->vws = vws;
@@ -682,6 +808,8 @@ vmw_svga_winsys_context_create(struct svga_winsys_screen *sws)
out_no_hash:
pb_validate_destroy(vswc->validate);
out_no_validate:
+ vmw_ioctl_context_destroy(vws, vswc->base.cid);
+out_no_context:
FREE(vswc);
return NULL;
}