diff options
Diffstat (limited to 'src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp')
-rw-r--r-- | src/gallium/winsys/d3d12/wgl/d3d12_wgl_framebuffer.cpp | 147 |
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; } |