#include "texture9.h"
#include "cubetexture9.h"
#include "volumetexture9.h"
+#include "nine_buffer_upload.h"
#include "nine_helpers.h"
#include "nine_pipe.h"
#include "nine_ff.h"
This->caps.MaxVertexShaderConst = NINE_MAX_CONST_F_SWVP;
This->context.pipe = This->screen->context_create(This->screen, NULL, 0);
- if (!This->context.pipe) { return E_OUTOFMEMORY; } /* guess */
+ This->pipe_secondary = This->screen->context_create(This->screen, NULL, 0);
+ if (!This->context.pipe || !This->pipe_secondary) { return E_OUTOFMEMORY; } /* guess */
This->pipe_sw = This->screen_sw->context_create(This->screen_sw, NULL, 0);
if (!This->pipe_sw) { return E_OUTOFMEMORY; }
- This->context.cso = cso_create_context(This->context.pipe);
+ This->context.cso = cso_create_context(This->context.pipe, 0);
if (!This->context.cso) { return E_OUTOFMEMORY; } /* also a guess */
- This->cso_sw = cso_create_context(This->pipe_sw);
+ This->cso_sw = cso_create_context(This->pipe_sw, 0);
if (!This->cso_sw) { return E_OUTOFMEMORY; }
/* Create first, it messes up our state. */
nine_bind(&This->context.rt[i], This->state.rt[i]);
}
+ /* Initialize CSMT */
+ if (pCTX->csmt_force == 1)
+ This->csmt_active = true;
+ else if (pCTX->csmt_force == 0)
+ This->csmt_active = false;
+ else
+ /* r600 and radeonsi are thread safe. */
+ This->csmt_active = strstr(pScreen->get_name(pScreen), "AMD") != NULL;
+
+ /* We rely on u_upload_mgr using persistent coherent buffers (which don't
+ * require flush to work in multi-pipe_context scenario) for vertex and
+ * index buffers */
+ if (!GET_PCAP(BUFFER_MAP_PERSISTENT_COHERENT))
+ This->csmt_active = false;
+
+ if (This->csmt_active) {
+ This->csmt_ctx = nine_csmt_create(This);
+ if (!This->csmt_ctx)
+ return E_OUTOFMEMORY;
+ }
+
+ if (This->csmt_active)
+ DBG("\033[1;32mCSMT is active\033[0m\n");
+
+ This->buffer_upload = nine_upload_create(This->pipe_secondary, 4 * 1024 * 1024, 4);
+
/* Initialize a dummy VBO to be used when a vertex declaration does not
* specify all the inputs needed by vertex shader, on win default behavior
* is to pass 0,0,0,0 to the shader */
/* Allocate upload helper for drivers that suck (from st pov ;). */
- This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS);
- This->driver_caps.user_ibufs = GET_PCAP(USER_INDEX_BUFFERS);
+ This->driver_caps.user_vbufs = GET_PCAP(USER_VERTEX_BUFFERS) && !This->csmt_active;
This->driver_caps.user_cbufs = GET_PCAP(USER_CONSTANT_BUFFERS);
This->driver_caps.user_sw_vbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_VERTEX_BUFFERS);
This->driver_caps.user_sw_cbufs = This->screen_sw->get_param(This->screen_sw, PIPE_CAP_USER_CONSTANT_BUFFERS);
-
- if (!This->driver_caps.user_vbufs)
- This->vertex_uploader = u_upload_create(This->context.pipe, 65536,
- PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM);
- This->vertex_sw_uploader = u_upload_create(This->pipe_sw, 65536,
- PIPE_BIND_VERTEX_BUFFER, PIPE_USAGE_STREAM);
- if (!This->driver_caps.user_ibufs)
- This->index_uploader = u_upload_create(This->context.pipe, 128 * 1024,
- PIPE_BIND_INDEX_BUFFER, PIPE_USAGE_STREAM);
- if (!This->driver_caps.user_cbufs) {
+ This->vertex_uploader = This->csmt_active ? This->pipe_secondary->stream_uploader : This->context.pipe->stream_uploader;
+ if (!This->driver_caps.user_cbufs)
This->constbuf_alignment = GET_PCAP(CONSTANT_BUFFER_OFFSET_ALIGNMENT);
- This->constbuf_uploader = u_upload_create(This->context.pipe, This->vs_const_size,
- PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM);
- }
-
- This->constbuf_sw_uploader = u_upload_create(This->pipe_sw, 128 * 1024,
- PIPE_BIND_CONSTANT_BUFFER, PIPE_USAGE_STREAM);
-
This->driver_caps.window_space_position_support = GET_PCAP(TGSI_VS_WINDOW_SPACE_POSITION);
This->driver_caps.vs_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_VERTEX, PIPE_SHADER_CAP_INTEGERS);
This->driver_caps.ps_integer = pScreen->get_shader_param(pScreen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_INTEGERS);
nine_state_init_sw(This);
ID3DPresentGroup_Release(This->present);
+ nine_csmt_process(This);
return D3D_OK;
}
DBG("This=%p\n", This);
+ /* Flush all pending commands to get refcount right,
+ * and properly release bound objects. It is ok to still
+ * execute commands while we are in device dtor, because
+ * we haven't released anything yet. Note that no pending
+ * command can increase the device refcount. */
+ if (This->csmt_active && This->csmt_ctx) {
+ nine_csmt_process(This);
+ nine_csmt_destroy(This, This->csmt_ctx);
+ This->csmt_active = FALSE;
+ This->csmt_ctx = NULL;
+ }
+
nine_ff_fini(This);
nine_state_destroy_sw(This);
nine_state_clear(&This->state, TRUE);
nine_context_clear(This);
- if (This->vertex_uploader)
- u_upload_destroy(This->vertex_uploader);
- if (This->index_uploader)
- u_upload_destroy(This->index_uploader);
- if (This->constbuf_uploader)
- u_upload_destroy(This->constbuf_uploader);
- if (This->vertex_sw_uploader)
- u_upload_destroy(This->vertex_sw_uploader);
- if (This->constbuf_sw_uploader)
- u_upload_destroy(This->constbuf_sw_uploader);
-
nine_bind(&This->record, NULL);
pipe_sampler_view_reference(&This->dummy_sampler_view, NULL);
FREE(This->swapchains);
}
+ if (This->buffer_upload)
+ nine_upload_destroy(This->buffer_upload);
+
/* Destroy cso first */
if (This->context.cso) { cso_destroy_context(This->context.cso); }
if (This->cso_sw) { cso_destroy_context(This->cso_sw); }
if (This->context.pipe && This->context.pipe->destroy) { This->context.pipe->destroy(This->context.pipe); }
+ if (This->pipe_secondary && This->pipe_secondary->destroy) { This->pipe_secondary->destroy(This->pipe_secondary); }
if (This->pipe_sw && This->pipe_sw->destroy) { This->pipe_sw->destroy(This->pipe_sw); }
if (This->present) { ID3DPresentGroup_Release(This->present); }
struct pipe_context *
NineDevice9_GetPipe( struct NineDevice9 *This )
{
- return This->context.pipe;
+ return nine_context_get_pipe(This);
}
const D3DCAPS9 *
break;
}
+ nine_csmt_process(This);
nine_state_clear(&This->state, TRUE);
nine_context_clear(This);
D3DTEXTUREFILTERTYPE Filter )
{
struct pipe_screen *screen = This->screen;
- struct pipe_context *pipe = NineDevice9_GetPipe(This);
struct NineSurface9 *dst = NineSurface9(pDestSurface);
struct NineSurface9 *src = NineSurface9(pSourceSurface);
struct pipe_resource *dst_res = NineSurface9_GetResource(dst);
PIPE_BIND_RENDER_TARGET),
D3DERR_INVALIDCALL);
- pipe->blit(pipe, &blit);
+ nine_context_blit(This, (struct NineUnknown *)dst,
+ (struct NineUnknown *)src, &blit);
} else {
assert(blit.dst.box.x >= 0 && blit.dst.box.y >= 0 &&
blit.src.box.x >= 0 && blit.src.box.y >= 0 &&
blit.src.box.y + blit.src.box.height <= src->desc.Height);
/* Or drivers might crash ... */
DBG("Using resource_copy_region.\n");
- pipe->resource_copy_region(pipe,
- blit.dst.resource, blit.dst.level,
- blit.dst.box.x, blit.dst.box.y, blit.dst.box.z,
- blit.src.resource, blit.src.level,
- &blit.src.box);
+ nine_context_resource_copy_region(This, (struct NineUnknown *)dst,
+ (struct NineUnknown *)src,
+ blit.dst.resource, blit.dst.level,
+ &blit.dst.box,
+ blit.src.resource, blit.src.level,
+ &blit.src.box);
}
/* Communicate the container it needs to update sublevels - if apply */
const RECT *pRect,
D3DCOLOR color )
{
- struct pipe_context *pipe = NineDevice9_GetPipe(This);
struct NineSurface9 *surf = NineSurface9(pSurface);
- struct pipe_surface *psurf;
unsigned x, y, w, h;
- union pipe_color_union rgba;
- boolean fallback;
DBG("This=%p pSurface=%p pRect=%p color=%08x\n", This,
pSurface, pRect, color);
w = surf->desc.Width;
h = surf->desc.Height;
}
- d3dcolor_to_pipe_color_union(&rgba, color);
-
- fallback = !(surf->base.info.bind & PIPE_BIND_RENDER_TARGET);
-
- if (!fallback) {
- psurf = NineSurface9_GetSurface(surf, 0);
- if (!psurf)
- fallback = TRUE;
- }
- if (!fallback) {
- pipe->clear_render_target(pipe, psurf, &rgba, x, y, w, h, false);
+ if (surf->base.info.bind & PIPE_BIND_RENDER_TARGET) {
+ nine_context_clear_render_target(This, surf, color, x, y, w, h);
} else {
D3DLOCKED_RECT lock;
union util_color uc;
HRESULT hr;
/* XXX: lock pRect and fix util_fill_rect */
- hr = NineSurface9_LockRect(surf, &lock, NULL, 0);
+ hr = NineSurface9_LockRect(surf, &lock, NULL, pRect ? 0 : D3DLOCK_DISCARD);
if (FAILED(hr))
return hr;
util_pack_color_ub(color >> 16, color >> 8, color >> 0, color >> 24,
if (unlikely(This->is_recording))
state->changed.ucp |= 1 << Index;
else
- nine_context_set_clip_plane(This, Index, pPlane);
+ nine_context_set_clip_plane(This, Index, (struct nine_clipplane *)pPlane);
return D3D_OK;
}
if (old == tex)
return D3D_OK;
- if (tex) {
- if ((tex->managed.dirty | tex->dirty_mip) && LIST_IS_EMPTY(&tex->list))
- list_add(&tex->list, &This->update_textures);
-
- tex->bind_count++;
- }
- if (old)
- old->bind_count--;
+ NineBindTextureToDevice(This, &state->texture[Stage], tex);
nine_context_set_texture(This, Stage, tex);
- nine_bind(&state->texture[Stage], pTexture);
-
return D3D_OK;
}
vtxbuf.stride = VertexStreamZeroStride;
vtxbuf.buffer_offset = 0;
- vtxbuf.buffer = NULL;
- vtxbuf.user_buffer = pVertexStreamZeroData;
+ vtxbuf.is_user_buffer = true;
+ vtxbuf.buffer.user = pVertexStreamZeroData;
if (!This->driver_caps.user_vbufs) {
+ vtxbuf.is_user_buffer = false;
+ vtxbuf.buffer.resource = NULL;
u_upload_data(This->vertex_uploader,
0,
(prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * VertexStreamZeroStride, /* XXX */
4,
- vtxbuf.user_buffer,
+ pVertexStreamZeroData,
&vtxbuf.buffer_offset,
- &vtxbuf.buffer);
+ &vtxbuf.buffer.resource);
u_upload_unmap(This->vertex_uploader);
- vtxbuf.user_buffer = NULL;
}
NineBeforeDraw(This);
nine_context_draw_primitive_from_vtxbuf(This, PrimitiveType, PrimitiveCount, &vtxbuf);
NineAfterDraw(This);
- pipe_resource_reference(&vtxbuf.buffer, NULL);
+ pipe_vertex_buffer_unreference(&vtxbuf);
NineDevice9_PauseRecording(This);
NineDevice9_SetStreamSource(This, 0, NULL, 0, 0);
UINT VertexStreamZeroStride )
{
struct pipe_vertex_buffer vbuf;
- struct pipe_index_buffer ibuf;
DBG("iface %p, PrimitiveType %u, MinVertexIndex %u, NumVertices %u "
"PrimitiveCount %u, pIndexData %p, IndexDataFormat %u "
vbuf.stride = VertexStreamZeroStride;
vbuf.buffer_offset = 0;
- vbuf.buffer = NULL;
- vbuf.user_buffer = pVertexStreamZeroData;
+ vbuf.is_user_buffer = true;
+ vbuf.buffer.user = pVertexStreamZeroData;
- ibuf.index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4;
- ibuf.offset = 0;
- ibuf.buffer = NULL;
- ibuf.user_buffer = pIndexData;
+ unsigned index_size = (IndexDataFormat == D3DFMT_INDEX16) ? 2 : 4;
+ struct pipe_resource *ibuf = NULL;
if (!This->driver_caps.user_vbufs) {
const unsigned base = MinVertexIndex * VertexStreamZeroStride;
+ vbuf.is_user_buffer = false;
+ vbuf.buffer.resource = NULL;
u_upload_data(This->vertex_uploader,
base,
NumVertices * VertexStreamZeroStride, /* XXX */
4,
- (const uint8_t *)vbuf.user_buffer + base,
+ (const uint8_t *)pVertexStreamZeroData + base,
&vbuf.buffer_offset,
- &vbuf.buffer);
+ &vbuf.buffer.resource);
u_upload_unmap(This->vertex_uploader);
/* Won't be used: */
vbuf.buffer_offset -= base;
- vbuf.user_buffer = NULL;
}
- if (!This->driver_caps.user_ibufs) {
- u_upload_data(This->index_uploader,
+
+ unsigned index_offset = 0;
+ if (This->csmt_active) {
+ u_upload_data(This->pipe_secondary->stream_uploader,
0,
- (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * ibuf.index_size,
+ (prim_count_to_vertex_count(PrimitiveType, PrimitiveCount)) * index_size,
4,
- ibuf.user_buffer,
- &ibuf.offset,
- &ibuf.buffer);
- u_upload_unmap(This->index_uploader);
- ibuf.user_buffer = NULL;
+ pIndexData,
+ &index_offset,
+ &ibuf);
+ u_upload_unmap(This->pipe_secondary->stream_uploader);
}
NineBeforeDraw(This);
NumVertices,
PrimitiveCount,
&vbuf,
- &ibuf);
+ ibuf,
+ ibuf ? NULL : (void*)pIndexData,
+ index_offset,
+ index_size);
NineAfterDraw(This);
- pipe_resource_reference(&vbuf.buffer, NULL);
- pipe_resource_reference(&ibuf.buffer, NULL);
+ pipe_vertex_buffer_unreference(&vbuf);
+ pipe_resource_reference(&ibuf, NULL);
NineDevice9_PauseRecording(This);
NineDevice9_SetIndices(This, NULL);
draw.restart_index = 0;
draw.count_from_stream_output = NULL;
draw.indirect = NULL;
- draw.indirect_params = NULL;
draw.instance_count = 1;
- draw.indexed = FALSE;
+ draw.index_size = 0;
draw.start = 0;
draw.index_bias = 0;
draw.min_index = 0;
pConstantData,
Vector4fCount * 4 * sizeof(state->vs_const_f[0]));
- nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData, Vector4fCount);
+ nine_context_set_vertex_shader_constant_f(This, StartRegister, pConstantData,
+ Vector4fCount * 4 * sizeof(state->vs_const_f[0]),
+ Vector4fCount);
return D3D_OK;
}
&This->range_pool);
state->changed.group |= NINE_STATE_VS_CONST;
} else
- nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData, Vector4iCount);
+ nine_context_set_vertex_shader_constant_i(This, StartRegister, pConstantData,
+ Vector4iCount * sizeof(int[4]), Vector4iCount);
return D3D_OK;
}
&This->range_pool);
state->changed.group |= NINE_STATE_VS_CONST;
} else
- nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData, BoolCount);
+ nine_context_set_vertex_shader_constant_b(This, StartRegister, pConstantData,
+ sizeof(BOOL) * BoolCount, BoolCount);
return D3D_OK;
}
state->vtxbuf[i].stride = Stride;
state->vtxbuf[i].buffer_offset = OffsetInBytes;
- nine_bind(&state->stream[i], pStreamData);
+ NineBindBufferToDevice(This,
+ (struct NineBuffer9 **)&state->stream[i],
+ (struct NineBuffer9 *)pVBuf9);
nine_context_set_stream_source(This,
StreamNumber,
if (state->idxbuf == idxbuf)
return D3D_OK;
- nine_bind(&state->idxbuf, idxbuf);
+
+ NineBindBufferToDevice(This,
+ (struct NineBuffer9 **)&state->idxbuf,
+ (struct NineBuffer9 *)idxbuf);
nine_context_set_indices(This, idxbuf);
pConstantData,
Vector4fCount * 4 * sizeof(state->ps_const_f[0]));
- nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData, Vector4fCount);
+ nine_context_set_pixel_shader_constant_f(This, StartRegister, pConstantData,
+ Vector4fCount * 4 * sizeof(state->ps_const_f[0]),
+ Vector4fCount);
return D3D_OK;
}
state->changed.ps_const_i |= ((1 << Vector4iCount) - 1) << StartRegister;
state->changed.group |= NINE_STATE_PS_CONST;
} else
- nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData, Vector4iCount);
+ nine_context_set_pixel_shader_constant_i(This, StartRegister, pConstantData,
+ sizeof(state->ps_const_i[0]) * Vector4iCount, Vector4iCount);
return D3D_OK;
}
state->changed.ps_const_b |= ((1 << BoolCount) - 1) << StartRegister;
state->changed.group |= NINE_STATE_PS_CONST;
} else
- nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData, BoolCount);
+ nine_context_set_pixel_shader_constant_b(This, StartRegister, pConstantData,
+ sizeof(BOOL) * BoolCount, BoolCount);
return D3D_OK;
}