summaryrefslogtreecommitdiffstats
path: root/video/out/d3d11/ra_d3d11.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/out/d3d11/ra_d3d11.c')
-rw-r--r--video/out/d3d11/ra_d3d11.c63
1 files changed, 15 insertions, 48 deletions
diff --git a/video/out/d3d11/ra_d3d11.c b/video/out/d3d11/ra_d3d11.c
index 63dc5b9509..4246a8d71e 100644
--- a/video/out/d3d11/ra_d3d11.c
+++ b/video/out/d3d11/ra_d3d11.c
@@ -86,9 +86,9 @@ struct d3d_tex {
struct d3d_buf {
ID3D11Buffer *buf;
- ID3D11Buffer *staging;
ID3D11UnorderedAccessView *uav;
- void *data; // Data for mapped staging texture
+ void *data; // System-memory mirror of the data in buf
+ bool dirty; // Is buf out of date?
};
struct d3d_rpass {
@@ -655,13 +655,8 @@ static void buf_destroy(struct ra *ra, struct ra_buf *buf)
{
if (!buf)
return;
- struct ra_d3d11 *p = ra->priv;
struct d3d_buf *buf_p = buf->priv;
-
- if (buf_p->data)
- ID3D11DeviceContext_Unmap(p->ctx, (ID3D11Resource *)buf_p->staging, 0);
SAFE_RELEASE(buf_p->buf);
- SAFE_RELEASE(buf_p->staging);
SAFE_RELEASE(buf_p->uav);
talloc_free(buf);
}
@@ -705,24 +700,13 @@ static struct ra_buf *buf_create(struct ra *ra,
goto error;
}
- if (params->host_mutable) {
- // D3D11 doesn't allow constant buffer updates that aren't aligned to a
- // full constant boundary (vec4,) and some drivers don't allow partial
- // constant buffer updates at all, but the RA consumer is allowed to
- // partially update an ra_buf. The best way to handle partial updates
- // without causing a pipeline stall is probably to keep a copy of the
- // data in a staging buffer.
-
- desc.Usage = D3D11_USAGE_STAGING;
- desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
- desc.BindFlags = 0;
- hr = ID3D11Device_CreateBuffer(p->dev, &desc, NULL, &buf_p->staging);
- if (FAILED(hr)) {
- MP_ERR(ra, "Failed to create staging buffer: %s\n",
- mp_HRESULT_to_str(hr));
- goto error;
- }
- }
+ // D3D11 doesn't allow constant buffer updates that aren't aligned to a
+ // full constant boundary (vec4,) and some drivers don't allow partial
+ // constant buffer updates at all. To support partial buffer updates, keep
+ // a mirror of the buffer data in system memory and upload the whole thing
+ // before the buffer is used.
+ if (params->host_mutable)
+ buf_p->data = talloc_zero_size(buf, desc.ByteWidth);
if (params->type == RA_BUF_TYPE_SHADER_STORAGE) {
D3D11_UNORDERED_ACCESS_VIEW_DESC udesc = {
@@ -752,40 +736,23 @@ static void buf_resolve(struct ra *ra, struct ra_buf *buf)
struct ra_d3d11 *p = ra->priv;
struct d3d_buf *buf_p = buf->priv;
- assert(buf->params.host_mutable);
- if (!buf_p->data)
+ if (!buf->params.host_mutable || !buf_p->dirty)
return;
- ID3D11DeviceContext_Unmap(p->ctx, (ID3D11Resource *)buf_p->staging, 0);
- buf_p->data = NULL;
-
- // Synchronize the GPU buffer with the staging buffer
- ID3D11DeviceContext_CopyResource(p->ctx, (ID3D11Resource *)buf_p->buf,
- (ID3D11Resource *)buf_p->staging);
+ // Synchronize the GPU buffer with the system-memory copy
+ ID3D11DeviceContext_UpdateSubresource(p->ctx, (ID3D11Resource *)buf_p->buf,
+ 0, NULL, buf_p->data, 0, 0);
+ buf_p->dirty = false;
}
static void buf_update(struct ra *ra, struct ra_buf *buf, ptrdiff_t offset,
const void *data, size_t size)
{
- struct ra_d3d11 *p = ra->priv;
struct d3d_buf *buf_p = buf->priv;
- HRESULT hr;
-
- if (!buf_p->data) {
- // If this is the first update after the buffer was created or after it
- // has been used in a renderpass, it will be unmapped, so map it
- D3D11_MAPPED_SUBRESOURCE map = {0};
- hr = ID3D11DeviceContext_Map(p->ctx, (ID3D11Resource *)buf_p->staging,
- 0, D3D11_MAP_WRITE, 0, &map);
- if (FAILED(hr)) {
- MP_ERR(ra, "Failed to map resource\n");
- return;
- }
- buf_p->data = map.pData;
- }
char *cdata = buf_p->data;
memcpy(cdata + offset, data, size);
+ buf_p->dirty = true;
}
static const char *get_shader_target(struct ra *ra, enum glsl_shader type)