Skip to content

Commit

Permalink
[d3d9] Implement presentation regions
Browse files Browse the repository at this point in the history
  • Loading branch information
misyltoad committed Aug 25, 2019
1 parent 8663591 commit 3ff1782
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 29 deletions.
94 changes: 69 additions & 25 deletions src/d3d9/d3d9_swapchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
#include "d3d9_surface.h"
#include "d3d9_monitor.h"

#include <dxgi_presenter_frag.h>
#include <dxgi_presenter_vert.h>
#include <d3d9_presenter_frag.h>
#include <d3d9_presenter_vert.h>

namespace dxvk {

Expand All @@ -14,6 +14,12 @@ namespace dxvk {
}


struct D3D9PresentInfo {
float scale[2];
float offset[2];
};


D3D9SwapChainEx::D3D9SwapChainEx(
D3D9DeviceEx* pDevice,
D3DPRESENT_PARAMETERS* pPresentParams,
Expand All @@ -27,7 +33,7 @@ namespace dxvk {
m_presentParams = *pPresentParams;
m_window = m_presentParams.hDeviceWindow;

UpdatePresentExtent(nullptr);
UpdatePresentRegion(nullptr, nullptr);
if (!pDevice->GetOptions()->deferSurfaceCreation)
CreatePresenter();

Expand Down Expand Up @@ -109,11 +115,12 @@ namespace dxvk {
recreate |= m_presenter == nullptr;
recreate |= window != m_window;

m_window = window;

m_dirty |= vsync != m_vsync;
m_dirty |= UpdatePresentExtent(pSourceRect);
m_dirty |= UpdatePresentRegion(pSourceRect, pDestRect);
m_dirty |= recreate;
m_vsync = vsync;
m_window = window;

if (recreate)
CreatePresenter();
Expand Down Expand Up @@ -314,7 +321,7 @@ namespace dxvk {
}

m_presentParams = *pPresentParams;
UpdatePresentExtent(nullptr);
UpdatePresentRegion(nullptr, nullptr);
CreateBackBuffer();
return D3D_OK;
}
Expand Down Expand Up @@ -463,18 +470,27 @@ namespace dxvk {
m_context->bindRenderTargets(renderTargets, false);

VkViewport viewport;
viewport.x = 0.0f;
viewport.y = 0.0f;
viewport.width = float(m_swapImage->info().extent.width);
viewport.height = float(m_swapImage->info().extent.height);
viewport.x = float(m_dstRect.left);
viewport.y = float(m_dstRect.top);
viewport.width = float(info.imageExtent.width - m_dstRect.left);
viewport.height = float(info.imageExtent.height - m_dstRect.top);
viewport.minDepth = 0.0f;
viewport.maxDepth = 1.0f;

D3D9PresentInfo presentInfoConsts;
presentInfoConsts.scale[0] = float(m_srcRect.right - m_srcRect.left) / float(m_swapImage->info().extent.width);
presentInfoConsts.scale[1] = float(m_srcRect.bottom - m_srcRect.top) / float(m_swapImage->info().extent.height);

presentInfoConsts.offset[0] = float(m_srcRect.left) / float(m_swapImage->info().extent.width);
presentInfoConsts.offset[1] = float(m_srcRect.top) / float(m_swapImage->info().extent.height);

m_context->pushConstants(0, sizeof(D3D9PresentInfo), &presentInfoConsts);

VkRect2D scissor;
scissor.offset.x = 0;
scissor.offset.y = 0;
scissor.extent.width = info.imageExtent.width;
scissor.extent.height = info.imageExtent.height;
scissor.extent.width = info.imageExtent.width - m_dstRect.left;
scissor.extent.height = info.imageExtent.height - m_dstRect.top;

m_context->setViewports(1, &viewport, &scissor);

Expand Down Expand Up @@ -530,7 +546,7 @@ namespace dxvk {
m_presentStatus.result = VK_SUCCESS;

vk::PresenterDesc presenterDesc;
presenterDesc.imageExtent = m_presentExtent;
presenterDesc.imageExtent = GetPresentExtent();
presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1);
presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats);
presenterDesc.numPresentModes = PickPresentModes(Vsync, presenterDesc.presentModes);
Expand All @@ -551,7 +567,7 @@ namespace dxvk {
presenterDevice.adapter = m_device->adapter()->handle();

vk::PresenterDesc presenterDesc;
presenterDesc.imageExtent = m_presentExtent;
presenterDesc.imageExtent = GetPresentExtent();
presenterDesc.imageCount = PickImageCount(m_presentParams.BackBufferCount + 1);
presenterDesc.numFormats = PickFormats(EnumerateFormat(m_presentParams.BackBufferFormat), presenterDesc.formats);
presenterDesc.numPresentModes = PickPresentModes(false, presenterDesc.presentModes);
Expand Down Expand Up @@ -864,8 +880,8 @@ namespace dxvk {


void D3D9SwapChainEx::InitShaders() {
const SpirvCodeBuffer vsCode(dxgi_presenter_vert);
const SpirvCodeBuffer fsCode(dxgi_presenter_frag);
const SpirvCodeBuffer vsCode(d3d9_presenter_vert);
const SpirvCodeBuffer fsCode(d3d9_presenter_frag);

const std::array<DxvkResourceSlot, 2> fsResourceSlots = {{
{ BindingIds::Image, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D },
Expand All @@ -874,7 +890,9 @@ namespace dxvk {

m_vertShader = m_device->createShader(
VK_SHADER_STAGE_VERTEX_BIT,
0, nullptr, { 0u, 1u },
0, nullptr,
{ 0u, 1u,
0u, sizeof(D3D9PresentInfo) },
vsCode);

m_fragShader = m_device->createShader(
Expand Down Expand Up @@ -1071,17 +1089,43 @@ namespace dxvk {
return SetMonitorDisplayMode(GetDefaultMonitor(), &mode);
}

bool D3D9SwapChainEx::UpdatePresentExtent(const RECT* pSourceRect) {
VkExtent2D oldExtent = m_presentExtent;

if (pSourceRect != nullptr)
m_presentExtent = VkExtent2D{ uint32_t(pSourceRect->right - pSourceRect->left), uint32_t(pSourceRect->bottom - pSourceRect->top) };
bool D3D9SwapChainEx::UpdatePresentRegion(const RECT* pSourceRect, const RECT* pDestRect) {
if (pSourceRect == nullptr) {
m_srcRect.top = 0;
m_srcRect.left = 0;
m_srcRect.right = m_presentParams.BackBufferWidth;
m_srcRect.bottom = m_presentParams.BackBufferHeight;
}
else
m_srcRect = *pSourceRect;

RECT dstRect;
if (pDestRect == nullptr) {
// TODO: Should we hook WM_SIZE message for this?
UINT width, height;
GetWindowClientSize(m_window, &width, &height);

dstRect.top = 0;
dstRect.left = 0;
dstRect.right = LONG(width);
dstRect.bottom = LONG(height);
}
else
m_presentExtent = VkExtent2D{ m_presentParams.BackBufferWidth, m_presentParams.BackBufferHeight };
dstRect = *pDestRect;

m_presentExtent = VkExtent2D{ std::max(m_presentExtent.width, 1u), std::max(m_presentExtent.height, 1u) };
bool recreate =
m_dstRect.left != dstRect.left
|| m_dstRect.top != dstRect.top
|| m_dstRect.right != dstRect.right
|| m_dstRect.bottom != dstRect.bottom;

m_dstRect = dstRect;

return recreate;
}

return m_presentExtent != oldExtent;
VkExtent2D D3D9SwapChainEx::GetPresentExtent() {
return VkExtent2D{ uint32_t(m_dstRect.right - m_dstRect.left), uint32_t(m_dstRect.bottom - m_dstRect.top) };
}

void D3D9SwapChainEx::UpdateMonitorInfo() {
Expand Down
8 changes: 6 additions & 2 deletions src/d3d9/d3d9_swapchain.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,9 @@ namespace dxvk {
DxvkBlendMode m_blendMode;

D3D9Surface* m_backBuffer = nullptr;
VkExtent2D m_presentExtent;

RECT m_srcRect;
RECT m_dstRect;

DxvkSubmitStatus m_presentStatus;

Expand Down Expand Up @@ -196,7 +198,9 @@ namespace dxvk {

void UpdateMonitorInfo();

bool UpdatePresentExtent(const RECT* pSourceRect);
bool UpdatePresentRegion(const RECT* pSourceRect, const RECT* pDestRect);

VkExtent2D GetPresentExtent();

};

Expand Down
4 changes: 2 additions & 2 deletions src/d3d9/meson.build
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
d3d9_res = wrc_generator.process('version.rc')

d3d9_shaders = files([
'../dxgi/shaders/dxgi_presenter_frag.frag',
'../dxgi/shaders/dxgi_presenter_vert.vert',
'shaders/d3d9_presenter_frag.frag',
'shaders/d3d9_presenter_vert.vert',
])

d3d9_src = [
Expand Down
21 changes: 21 additions & 0 deletions src/d3d9/shaders/d3d9_presenter_frag.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#version 450

layout(constant_id = 1) const bool s_gamma_bound = true;

layout(binding = 0) uniform sampler2D s_image;
layout(binding = 1) uniform sampler1D s_gamma;

layout(location = 0) in vec2 i_texcoord;
layout(location = 0) out vec4 o_color;

void main() {
o_color = texture(s_image, i_texcoord);

if (s_gamma_bound) {
o_color = vec4(
texture(s_gamma, o_color.r).r,
texture(s_gamma, o_color.g).g,
texture(s_gamma, o_color.b).b,
o_color.a);
}
}
21 changes: 21 additions & 0 deletions src/d3d9/shaders/d3d9_presenter_vert.vert
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#version 450

layout(location = 0) out vec2 o_texcoord;

layout(push_constant) uniform present_info_t {
vec2 scale;
vec2 offset;
} u_presentInfo;

void main() {
vec2 coord = vec2(
float(gl_VertexIndex & 2),
float(gl_VertexIndex & 1) * 2.0f);

gl_Position = vec4(-1.0f + 2.0f * coord, 0.0f, 1.0f);

coord *= u_presentInfo.scale;
coord += u_presentInfo.offset;

o_texcoord = coord;
}

0 comments on commit 3ff1782

Please sign in to comment.