summaryrefslogtreecommitdiff
path: root/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp')
-rw-r--r--src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp147
1 files changed, 103 insertions, 44 deletions
diff --git a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
index e9a343b90e2..56e38fe7705 100644
--- a/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
+++ b/src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp
@@ -23,10 +23,13 @@
#include "d3d12_wgl_public.h"
-#include <Windows.h>
+#include <new>
+
+#include <windows.h>
#include <dxgi1_4.h>
#include <directx/d3d12.h>
#include <wrl.h>
+#include <dxguids/dxguids.h>
#include "util/u_memory.h"
#include "util/u_inlines.h"
@@ -52,6 +55,8 @@ struct d3d12_wgl_framebuffer {
HWND window;
ComPtr<IDXGISwapChain3> swapchain;
struct pipe_resource *buffers[num_buffers];
+ bool single_buffered;
+ struct pipe_resource *offscreen_buffer;
};
static struct d3d12_wgl_framebuffer *
@@ -71,7 +76,7 @@ d3d12_wgl_framebuffer_destroy(struct stw_winsys_framebuffer *fb,
/* Ensure all resources are flushed */
ctx->flush(ctx, &fence, PIPE_FLUSH_HINT_FINISH);
if (fence) {
- ctx->screen->fence_finish(ctx->screen, ctx, fence, PIPE_TIMEOUT_INFINITE);
+ ctx->screen->fence_finish(ctx->screen, ctx, fence, OS_TIMEOUT_INFINITE);
ctx->screen->fence_reference(ctx->screen, &fence, NULL);
}
}
@@ -83,6 +88,10 @@ d3d12_wgl_framebuffer_destroy(struct stw_winsys_framebuffer *fb,
}
}
+ if (framebuffer->offscreen_buffer) {
+ pipe_resource_reference(&framebuffer->offscreen_buffer, NULL);
+ }
+
delete framebuffer;
}
@@ -130,7 +139,7 @@ d3d12_wgl_framebuffer_resize(stw_winsys_framebuffer *fb,
/* Ensure all resources are flushed */
ctx->flush(ctx, &fence, PIPE_FLUSH_HINT_FINISH);
if (fence) {
- ctx->screen->fence_finish(ctx->screen, ctx, fence, PIPE_TIMEOUT_INFINITE);
+ ctx->screen->fence_finish(ctx->screen, ctx, fence, OS_TIMEOUT_INFINITE);
ctx->screen->fence_reference(ctx->screen, &fence, NULL);
}
@@ -144,10 +153,52 @@ d3d12_wgl_framebuffer_resize(stw_winsys_framebuffer *fb,
debug_printf("D3D12: failed to resize swapchain");
}
}
+
+ for (uint32_t i = 0; i < num_buffers; ++i) {
+ ID3D12Resource *res;
+ framebuffer->swapchain->GetBuffer(i, IID_PPV_ARGS(&res));
+ if (!res)
+ continue;
+
+ struct winsys_handle handle;
+ memset(&handle, 0, sizeof(handle));
+ handle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
+ handle.format = framebuffer->pformat;
+ handle.com_obj = res;
+
+ D3D12_RESOURCE_DESC res_desc = GetDesc(res);
+
+ struct pipe_resource templ;
+ memset(&templ, 0, sizeof(templ));
+ templ.target = PIPE_TEXTURE_2D;
+ templ.format = framebuffer->pformat;
+ templ.width0 = res_desc.Width;
+ templ.height0 = res_desc.Height;
+ templ.depth0 = 1;
+ templ.array_size = res_desc.DepthOrArraySize;
+ templ.nr_samples = res_desc.SampleDesc.Count;
+ templ.last_level = res_desc.MipLevels - 1;
+ templ.bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
+ templ.usage = PIPE_USAGE_DEFAULT;
+ templ.flags = 0;
+
+ pipe_resource_reference(&framebuffer->buffers[i],
+ screen->base.base.resource_from_handle(&screen->base.base, &templ, &handle,
+ PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
+ }
+
+ if (framebuffer->single_buffered) {
+ if (framebuffer->offscreen_buffer) {
+ pipe_resource_reference(&framebuffer->offscreen_buffer, NULL);
+ }
+ struct pipe_resource local_templ = *templ;
+ local_templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;
+ framebuffer->offscreen_buffer = screen->base.base.resource_create(&screen->base.base, &local_templ);
+ }
}
-static boolean
-d3d12_wgl_framebuffer_present(stw_winsys_framebuffer *fb)
+static bool
+d3d12_wgl_framebuffer_present(stw_winsys_framebuffer *fb, int interval)
{
auto framebuffer = d3d12_wgl_framebuffer(fb);
if (!framebuffer->swapchain) {
@@ -155,10 +206,10 @@ d3d12_wgl_framebuffer_present(stw_winsys_framebuffer *fb)
return false;
}
- if (stw_dev->swap_interval < 1)
+ if (interval < 1)
return S_OK == framebuffer->swapchain->Present(0, DXGI_PRESENT_ALLOW_TEARING);
else
- return S_OK == framebuffer->swapchain->Present(stw_dev->swap_interval, 0);
+ return S_OK == framebuffer->swapchain->Present(interval, 0);
}
static struct pipe_resource *
@@ -166,52 +217,53 @@ d3d12_wgl_framebuffer_get_resource(struct stw_winsys_framebuffer *pframebuffer,
st_attachment_type statt)
{
auto framebuffer = d3d12_wgl_framebuffer(pframebuffer);
- auto pscreen = &framebuffer->screen->base;
if (!framebuffer->swapchain)
return nullptr;
+ if (framebuffer->single_buffered) {
+ assert(statt == ST_ATTACHMENT_FRONT_LEFT);
+ assert(framebuffer->offscreen_buffer);
+ pipe_reference(NULL, &framebuffer->offscreen_buffer->reference);
+ return framebuffer->offscreen_buffer;
+ }
+
UINT index = framebuffer->swapchain->GetCurrentBackBufferIndex();
if (statt == ST_ATTACHMENT_FRONT_LEFT)
index = !index;
- if (framebuffer->buffers[index]) {
- pipe_reference(NULL, &framebuffer->buffers[index]->reference);
- return framebuffer->buffers[index];
- }
-
- ID3D12Resource *res;
- framebuffer->swapchain->GetBuffer(index, IID_PPV_ARGS(&res));
- if (!res)
- return nullptr;
-
- struct winsys_handle handle;
- memset(&handle, 0, sizeof(handle));
- handle.type = WINSYS_HANDLE_TYPE_D3D12_RES;
- handle.com_obj = res;
-
- D3D12_RESOURCE_DESC res_desc = res->GetDesc();
-
- struct pipe_resource templ;
- memset(&templ, 0, sizeof(templ));
- templ.target = PIPE_TEXTURE_2D;
- templ.format = framebuffer->pformat;
- templ.width0 = res_desc.Width;
- templ.height0 = res_desc.Height;
- templ.depth0 = 1;
- templ.array_size = res_desc.DepthOrArraySize;
- templ.nr_samples = res_desc.SampleDesc.Count;
- templ.last_level = res_desc.MipLevels - 1;
- templ.bind = PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_RENDER_TARGET;
- templ.usage = PIPE_USAGE_DEFAULT;
- templ.flags = 0;
-
- pipe_resource_reference(&framebuffer->buffers[index],
- pscreen->resource_from_handle(pscreen, &templ, &handle,
- PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE));
+ assert(framebuffer->buffers[index]);
+ pipe_reference(NULL, &framebuffer->buffers[index]->reference);
return framebuffer->buffers[index];
}
+static void
+d3d12_wgl_framebuffer_flush_frontbuffer(struct stw_winsys_framebuffer *pframebuffer,
+ struct pipe_context *pipe)
+{
+ auto framebuffer = d3d12_wgl_framebuffer(pframebuffer);
+ struct pipe_blit_info blit;
+
+ memset(&blit, 0, sizeof(blit));
+ uint32_t index = framebuffer->swapchain->GetCurrentBackBufferIndex();
+ blit.dst.resource = framebuffer->buffers[index];
+ blit.dst.box.width = blit.dst.resource->width0;
+ blit.dst.box.height = blit.dst.resource->height0;
+ blit.dst.box.depth = 1;
+ blit.dst.format = blit.dst.resource->format;
+ blit.src.resource = framebuffer->offscreen_buffer;
+ blit.src.box.width = blit.src.resource->width0;
+ blit.src.box.height = blit.src.resource->height0;
+ blit.src.box.depth = 1;
+ blit.src.format = blit.src.resource->format;
+ blit.mask = PIPE_MASK_RGBA;
+ blit.filter = PIPE_TEX_FILTER_NEAREST;
+
+ pipe->blit(pipe, &blit);
+ pipe->flush_resource(pipe, blit.dst.resource);
+ pipe->flush(pipe, NULL, 0);
+}
+
struct stw_winsys_framebuffer *
d3d12_wgl_create_framebuffer(struct pipe_screen *screen,
HWND hWnd,
@@ -219,8 +271,13 @@ d3d12_wgl_create_framebuffer(struct pipe_screen *screen,
{
const struct stw_pixelformat_info *pfi =
stw_pixelformat_get_info(iPixelFormat);
- if (!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ||
- (pfi->pfd.dwFlags & PFD_SUPPORT_GDI))
+ if ((pfi->pfd.dwFlags & PFD_SUPPORT_GDI))
+ return NULL;
+
+ if (pfi->stvis.color_format != PIPE_FORMAT_B8G8R8A8_UNORM &&
+ pfi->stvis.color_format != PIPE_FORMAT_R8G8B8A8_UNORM &&
+ pfi->stvis.color_format != PIPE_FORMAT_R10G10B10A2_UNORM &&
+ pfi->stvis.color_format != PIPE_FORMAT_R16G16B16A16_FLOAT)
return NULL;
struct d3d12_wgl_framebuffer *fb = CALLOC_STRUCT(d3d12_wgl_framebuffer);
@@ -231,10 +288,12 @@ d3d12_wgl_create_framebuffer(struct pipe_screen *screen,
fb->window = hWnd;
fb->screen = d3d12_screen(screen);
+ fb->single_buffered = (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) == 0;
fb->base.destroy = d3d12_wgl_framebuffer_destroy;
fb->base.resize = d3d12_wgl_framebuffer_resize;
fb->base.present = d3d12_wgl_framebuffer_present;
fb->base.get_resource = d3d12_wgl_framebuffer_get_resource;
+ fb->base.flush_frontbuffer = d3d12_wgl_framebuffer_flush_frontbuffer;
return &fb->base;
}