2015-05-24 04:55:12 +00:00
|
|
|
// Copyright 2010 Dolphin Emulator Project
|
2015-05-17 23:08:10 +00:00
|
|
|
// Licensed under GPLv2+
|
2013-04-18 03:29:41 +00:00
|
|
|
// Refer to the license.txt file included.
|
2010-06-13 19:50:06 +00:00
|
|
|
|
2017-01-23 16:20:20 +00:00
|
|
|
#include "VideoBackends/D3D/Render.h"
|
|
|
|
|
2017-04-09 20:15:57 +00:00
|
|
|
#include <array>
|
2013-10-26 09:55:41 +00:00
|
|
|
#include <cinttypes>
|
|
|
|
#include <cmath>
|
2017-04-09 21:27:20 +00:00
|
|
|
#include <cstring>
|
2015-12-22 23:47:20 +00:00
|
|
|
#include <memory>
|
2014-05-26 00:52:58 +00:00
|
|
|
#include <string>
|
2014-02-17 10:18:15 +00:00
|
|
|
#include <strsafe.h>
|
2017-04-09 19:05:24 +00:00
|
|
|
#include <tuple>
|
2010-06-13 19:50:06 +00:00
|
|
|
|
2017-09-08 09:42:56 +00:00
|
|
|
#include "Common/Assert.h"
|
2016-01-17 21:54:31 +00:00
|
|
|
#include "Common/CommonTypes.h"
|
2017-02-01 15:56:13 +00:00
|
|
|
#include "Common/Logging/Log.h"
|
2015-05-06 22:37:58 +00:00
|
|
|
#include "Common/MathUtil.h"
|
2010-06-13 19:50:06 +00:00
|
|
|
|
2014-02-19 11:14:09 +00:00
|
|
|
#include "Core/Core.h"
|
2011-01-25 16:43:08 +00:00
|
|
|
|
2014-12-05 02:01:20 +00:00
|
|
|
#include "VideoBackends/D3D/BoundingBox.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
#include "VideoBackends/D3D/D3DBase.h"
|
2014-06-23 06:11:07 +00:00
|
|
|
#include "VideoBackends/D3D/D3DState.h"
|
2017-09-08 09:42:56 +00:00
|
|
|
#include "VideoBackends/D3D/DXPipeline.h"
|
|
|
|
#include "VideoBackends/D3D/DXShader.h"
|
2017-05-29 22:02:09 +00:00
|
|
|
#include "VideoBackends/D3D/DXTexture.h"
|
2014-02-17 10:18:15 +00:00
|
|
|
|
|
|
|
#include "VideoCommon/BPFunctions.h"
|
2019-02-15 01:59:50 +00:00
|
|
|
#include "VideoCommon/FramebufferManager.h"
|
|
|
|
#include "VideoCommon/PostProcessing.h"
|
2017-04-29 14:54:22 +00:00
|
|
|
#include "VideoCommon/RenderState.h"
|
2017-09-03 02:30:34 +00:00
|
|
|
#include "VideoCommon/VideoConfig.h"
|
2017-02-01 15:56:13 +00:00
|
|
|
#include "VideoCommon/XFMemory.h"
|
2010-06-13 19:50:06 +00:00
|
|
|
|
2011-01-29 20:16:51 +00:00
|
|
|
namespace DX11
|
|
|
|
{
|
2014-11-29 20:37:34 +00:00
|
|
|
// Nvidia stereo blitting struct defined in "nvstereo.h" from the Nvidia SDK
|
2014-11-13 23:24:53 +00:00
|
|
|
typedef struct _Nv_Stereo_Image_Header
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
unsigned int dwSignature;
|
|
|
|
unsigned int dwWidth;
|
|
|
|
unsigned int dwHeight;
|
|
|
|
unsigned int dwBPP;
|
|
|
|
unsigned int dwFlags;
|
2014-11-13 23:24:53 +00:00
|
|
|
} NVSTEREOIMAGEHEADER, *LPNVSTEREOIMAGEHEADER;
|
|
|
|
|
|
|
|
#define NVSTEREO_IMAGE_SIGNATURE 0x4433564e
|
2011-09-08 13:39:03 +00:00
|
|
|
|
2019-01-18 14:35:00 +00:00
|
|
|
Renderer::Renderer(int backbuffer_width, int backbuffer_height, float backbuffer_scale)
|
|
|
|
: ::Renderer(backbuffer_width, backbuffer_height, backbuffer_scale,
|
|
|
|
AbstractTextureFormat::RGBA8)
|
2017-11-21 09:53:38 +00:00
|
|
|
{
|
2018-01-26 06:23:24 +00:00
|
|
|
m_last_fullscreen_state = D3D::GetFullscreenState();
|
2010-06-13 19:50:06 +00:00
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
Renderer::~Renderer() = default;
|
|
|
|
|
2017-11-21 09:53:38 +00:00
|
|
|
void Renderer::Create3DVisionTexture(int width, int height)
|
2014-11-13 23:24:53 +00:00
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// Create a staging texture for 3D vision with signature information in the last row.
|
|
|
|
// Nvidia 3D Vision supports full SBS, so there is no loss in resolution during this process.
|
2017-04-09 21:27:20 +00:00
|
|
|
NVSTEREOIMAGEHEADER header;
|
|
|
|
header.dwSignature = NVSTEREO_IMAGE_SIGNATURE;
|
|
|
|
header.dwWidth = static_cast<u32>(width * 2);
|
|
|
|
header.dwHeight = static_cast<u32>(height + 1);
|
|
|
|
header.dwBPP = 32;
|
|
|
|
header.dwFlags = 0;
|
|
|
|
|
|
|
|
const u32 pitch = static_cast<u32>(4 * width * 2);
|
|
|
|
const auto memory = std::make_unique<u8[]>((height + 1) * pitch);
|
|
|
|
u8* image_header_location = &memory[height * pitch];
|
|
|
|
std::memcpy(image_header_location, &header, sizeof(header));
|
|
|
|
|
|
|
|
D3D11_SUBRESOURCE_DATA sys_data;
|
|
|
|
sys_data.SysMemPitch = pitch;
|
|
|
|
sys_data.pSysMem = memory.get();
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
CD3D11_TEXTURE2D_DESC texture_desc(DXGI_FORMAT_R8G8B8A8_UNORM, width * 2, height + 1, 1, 1,
|
|
|
|
D3D11_BIND_RENDER_TARGET, D3D11_USAGE_DEFAULT, 0, 1, 0, 0);
|
|
|
|
ID3D11Texture2D* texture;
|
|
|
|
HRESULT hr = D3D::device->CreateTexture2D(&texture_desc, &sys_data, &texture);
|
|
|
|
CHECK(SUCCEEDED(hr), "Create 3D Vision Texture");
|
|
|
|
m_3d_vision_texture = std::make_unique<DXTexture>(TextureConfig(width * 2, height + 1, 1, 1, 1,
|
|
|
|
AbstractTextureFormat::RGBA8,
|
|
|
|
AbstractTextureFlag_RenderTarget),
|
|
|
|
texture, nullptr, nullptr);
|
|
|
|
m_3d_vision_framebuffer =
|
|
|
|
DXFramebuffer::Create(static_cast<DXTexture*>(m_3d_vision_texture.get()), nullptr);
|
2014-11-13 23:24:53 +00:00
|
|
|
}
|
|
|
|
|
2018-10-03 13:03:13 +00:00
|
|
|
bool Renderer::IsHeadless() const
|
|
|
|
{
|
|
|
|
return D3D::swapchain == nullptr;
|
|
|
|
}
|
|
|
|
|
2017-09-30 06:25:36 +00:00
|
|
|
std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config)
|
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
return DXTexture::Create(config);
|
2017-09-30 06:25:36 +00:00
|
|
|
}
|
|
|
|
|
2017-10-21 14:49:40 +00:00
|
|
|
std::unique_ptr<AbstractStagingTexture> Renderer::CreateStagingTexture(StagingTextureType type,
|
|
|
|
const TextureConfig& config)
|
|
|
|
{
|
|
|
|
return DXStagingTexture::Create(type, config);
|
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
std::unique_ptr<AbstractFramebuffer> Renderer::CreateFramebuffer(AbstractTexture* color_attachment,
|
|
|
|
AbstractTexture* depth_attachment)
|
2018-01-21 10:22:45 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
return DXFramebuffer::Create(static_cast<DXTexture*>(color_attachment),
|
|
|
|
static_cast<DXTexture*>(depth_attachment));
|
2018-01-21 10:22:45 +00:00
|
|
|
}
|
|
|
|
|
2017-09-08 09:42:56 +00:00
|
|
|
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromSource(ShaderStage stage,
|
|
|
|
const char* source, size_t length)
|
|
|
|
{
|
|
|
|
return DXShader::CreateFromSource(stage, source, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<AbstractShader> Renderer::CreateShaderFromBinary(ShaderStage stage,
|
|
|
|
const void* data, size_t length)
|
|
|
|
{
|
|
|
|
return DXShader::CreateFromBinary(stage, data, length);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<AbstractPipeline> Renderer::CreatePipeline(const AbstractPipelineConfig& config)
|
|
|
|
{
|
|
|
|
return DXPipeline::Create(config);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Renderer::SetPipeline(const AbstractPipeline* pipeline)
|
|
|
|
{
|
|
|
|
const DXPipeline* dx_pipeline = static_cast<const DXPipeline*>(pipeline);
|
2019-02-15 01:59:50 +00:00
|
|
|
if (m_current_pipeline == dx_pipeline)
|
2018-02-24 13:13:00 +00:00
|
|
|
return;
|
2017-09-08 09:42:56 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
if (dx_pipeline)
|
2016-06-24 08:43:46 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
D3D::stateman->SetRasterizerState(dx_pipeline->GetRasterizerState());
|
|
|
|
D3D::stateman->SetDepthState(dx_pipeline->GetDepthState());
|
|
|
|
D3D::stateman->SetBlendState(dx_pipeline->GetBlendState());
|
|
|
|
D3D::stateman->SetPrimitiveTopology(dx_pipeline->GetPrimitiveTopology());
|
|
|
|
D3D::stateman->SetInputLayout(dx_pipeline->GetInputLayout());
|
|
|
|
D3D::stateman->SetVertexShader(dx_pipeline->GetVertexShader());
|
|
|
|
D3D::stateman->SetGeometryShader(dx_pipeline->GetGeometryShader());
|
|
|
|
D3D::stateman->SetPixelShader(dx_pipeline->GetPixelShader());
|
|
|
|
D3D::stateman->SetIntegerRTV(dx_pipeline->UseLogicOp());
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
// These will be destroyed at pipeline destruction.
|
|
|
|
D3D::stateman->SetInputLayout(nullptr);
|
|
|
|
D3D::stateman->SetVertexShader(nullptr);
|
|
|
|
D3D::stateman->SetGeometryShader(nullptr);
|
|
|
|
D3D::stateman->SetPixelShader(nullptr);
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
2015-12-19 05:45:21 +00:00
|
|
|
}
|
2010-10-22 19:40:05 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::SetScissorRect(const MathUtil::Rectangle<int>& rc)
|
2015-12-19 05:45:21 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
// TODO: Move to stateman
|
|
|
|
const CD3D11_RECT rect(rc.left, rc.top, std::max(rc.right, rc.left + 1),
|
|
|
|
std::max(rc.bottom, rc.top + 1));
|
|
|
|
D3D::context->RSSetScissorRects(1, &rect);
|
2010-06-13 19:50:06 +00:00
|
|
|
}
|
|
|
|
|
2018-01-21 12:04:15 +00:00
|
|
|
void Renderer::SetViewport(float x, float y, float width, float height, float near_depth,
|
|
|
|
float far_depth)
|
2010-06-13 19:50:06 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
// TODO: Move to stateman
|
|
|
|
const CD3D11_VIEWPORT vp(x, y, width, height, near_depth, far_depth);
|
2016-06-24 08:43:46 +00:00
|
|
|
D3D::context->RSSetViewports(1, &vp);
|
2010-06-13 19:50:06 +00:00
|
|
|
}
|
2010-09-28 02:15:02 +00:00
|
|
|
|
2018-11-27 07:16:53 +00:00
|
|
|
void Renderer::Draw(u32 base_vertex, u32 num_vertices)
|
|
|
|
{
|
|
|
|
D3D::stateman->Apply();
|
|
|
|
D3D::context->Draw(num_vertices, base_vertex);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
|
|
|
|
{
|
|
|
|
D3D::stateman->Apply();
|
|
|
|
D3D::context->DrawIndexed(num_indices, base_index, base_vertex);
|
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::DispatchComputeShader(const AbstractShader* shader, u32 groups_x, u32 groups_y,
|
|
|
|
u32 groups_z)
|
2010-12-27 21:56:20 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
D3D::stateman->SetComputeShader(static_cast<const DXShader*>(shader)->GetD3DComputeShader());
|
|
|
|
D3D::stateman->SyncComputeBindings();
|
|
|
|
D3D::context->Dispatch(groups_x, groups_y, groups_z);
|
2010-12-27 21:56:20 +00:00
|
|
|
}
|
|
|
|
|
2018-11-28 04:30:47 +00:00
|
|
|
void Renderer::BindBackbuffer(const ClearColor& clear_color)
|
2010-06-13 19:50:06 +00:00
|
|
|
{
|
2018-01-26 06:23:24 +00:00
|
|
|
CheckForSurfaceChange();
|
|
|
|
CheckForSurfaceResize();
|
2019-02-15 01:59:50 +00:00
|
|
|
SetAndClearFramebuffer(D3D::GetSwapChainFramebuffer(), clear_color);
|
2018-11-28 04:30:47 +00:00
|
|
|
}
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2018-11-28 04:30:47 +00:00
|
|
|
void Renderer::PresentBackbuffer()
|
|
|
|
{
|
|
|
|
D3D::Present();
|
|
|
|
}
|
2016-06-24 08:43:46 +00:00
|
|
|
|
2018-11-28 04:30:47 +00:00
|
|
|
void Renderer::OnConfigChanged(u32 bits)
|
|
|
|
{
|
2010-06-13 19:50:06 +00:00
|
|
|
}
|
|
|
|
|
2018-01-26 06:23:24 +00:00
|
|
|
void Renderer::CheckForSurfaceChange()
|
|
|
|
{
|
|
|
|
if (!m_surface_changed.TestAndClear())
|
|
|
|
return;
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
m_3d_vision_framebuffer.reset();
|
|
|
|
m_3d_vision_texture.reset();
|
2018-10-03 13:03:13 +00:00
|
|
|
|
2018-01-26 06:23:24 +00:00
|
|
|
D3D::Reset(reinterpret_cast<HWND>(m_new_surface_handle));
|
2018-10-03 13:03:13 +00:00
|
|
|
m_new_surface_handle = nullptr;
|
|
|
|
|
2018-01-26 06:23:24 +00:00
|
|
|
UpdateBackbufferSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Renderer::CheckForSurfaceResize()
|
|
|
|
{
|
|
|
|
const bool fullscreen_state = D3D::GetFullscreenState();
|
|
|
|
const bool exclusive_fullscreen_changed = fullscreen_state != m_last_fullscreen_state;
|
|
|
|
if (!m_surface_resized.TestAndClear() && !exclusive_fullscreen_changed)
|
|
|
|
return;
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
m_3d_vision_framebuffer.reset();
|
|
|
|
m_3d_vision_texture.reset();
|
|
|
|
|
2018-01-26 06:23:24 +00:00
|
|
|
m_last_fullscreen_state = fullscreen_state;
|
|
|
|
if (D3D::swapchain)
|
|
|
|
D3D::ResizeSwapChain();
|
|
|
|
UpdateBackbufferSize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Renderer::UpdateBackbufferSize()
|
|
|
|
{
|
|
|
|
if (D3D::swapchain)
|
|
|
|
{
|
|
|
|
DXGI_SWAP_CHAIN_DESC1 desc = {};
|
|
|
|
D3D::swapchain->GetDesc1(&desc);
|
|
|
|
m_backbuffer_width = std::max(desc.Width, 1u);
|
|
|
|
m_backbuffer_height = std::max(desc.Height, 1u);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
m_backbuffer_width = 1;
|
|
|
|
m_backbuffer_height = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::SetFramebuffer(AbstractFramebuffer* framebuffer)
|
2010-06-13 19:50:06 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
if (m_current_framebuffer == framebuffer)
|
|
|
|
return;
|
2010-06-13 19:50:06 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
// We can't leave the framebuffer bound as a texture and a render target.
|
|
|
|
DXFramebuffer* fb = static_cast<DXFramebuffer*>(framebuffer);
|
|
|
|
if ((fb->GetColorAttachment() &&
|
|
|
|
D3D::stateman->UnsetTexture(
|
|
|
|
static_cast<DXTexture*>(fb->GetColorAttachment())->GetD3DSRV()) != 0) ||
|
|
|
|
(fb->GetDepthAttachment() &&
|
|
|
|
D3D::stateman->UnsetTexture(
|
|
|
|
static_cast<DXTexture*>(fb->GetDepthAttachment())->GetD3DSRV()) != 0))
|
|
|
|
{
|
|
|
|
D3D::stateman->ApplyTextures();
|
|
|
|
}
|
2010-06-13 19:50:06 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
D3D::stateman->SetFramebuffer(fb);
|
2018-01-21 10:22:45 +00:00
|
|
|
m_current_framebuffer = fb;
|
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::SetAndDiscardFramebuffer(AbstractFramebuffer* framebuffer)
|
2018-01-21 10:22:45 +00:00
|
|
|
{
|
|
|
|
SetFramebuffer(framebuffer);
|
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer,
|
2018-01-21 10:22:45 +00:00
|
|
|
const ClearColor& color_value, float depth_value)
|
|
|
|
{
|
|
|
|
SetFramebuffer(framebuffer);
|
2019-02-15 01:59:50 +00:00
|
|
|
D3D::stateman->Apply();
|
|
|
|
|
2018-01-21 10:22:45 +00:00
|
|
|
if (framebuffer->GetColorFormat() != AbstractTextureFormat::Undefined)
|
|
|
|
{
|
|
|
|
D3D::context->ClearRenderTargetView(
|
|
|
|
static_cast<const DXFramebuffer*>(framebuffer)->GetRTVArray()[0], color_value.data());
|
|
|
|
}
|
|
|
|
if (framebuffer->GetDepthFormat() != AbstractTextureFormat::Undefined)
|
|
|
|
{
|
|
|
|
D3D::context->ClearDepthStencilView(static_cast<const DXFramebuffer*>(framebuffer)->GetDSV(),
|
|
|
|
D3D11_CLEAR_DEPTH, depth_value, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-21 13:13:25 +00:00
|
|
|
void Renderer::SetTexture(u32 index, const AbstractTexture* texture)
|
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
D3D::stateman->SetTexture(index, texture ? static_cast<const DXTexture*>(texture)->GetD3DSRV() :
|
|
|
|
nullptr);
|
2018-01-21 13:13:25 +00:00
|
|
|
}
|
|
|
|
|
2017-09-09 08:30:15 +00:00
|
|
|
void Renderer::SetSamplerState(u32 index, const SamplerState& state)
|
2010-06-13 19:50:06 +00:00
|
|
|
{
|
2018-02-24 15:15:35 +00:00
|
|
|
D3D::stateman->SetSampler(index, m_state_cache.Get(state));
|
2010-06-13 19:50:06 +00:00
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::SetComputeImageTexture(AbstractTexture* texture, bool read, bool write)
|
2018-01-21 13:13:25 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
D3D::stateman->SetComputeUAV(texture ? static_cast<DXTexture*>(texture)->GetD3DUAV() : nullptr);
|
2018-01-21 13:13:25 +00:00
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::UnbindTexture(const AbstractTexture* texture)
|
2010-06-13 19:50:06 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
if (D3D::stateman->UnsetTexture(static_cast<const DXTexture*>(texture)->GetD3DSRV()) != 0)
|
|
|
|
D3D::stateman->ApplyTextures();
|
2010-06-13 19:50:06 +00:00
|
|
|
}
|
|
|
|
|
2014-12-05 02:01:20 +00:00
|
|
|
u16 Renderer::BBoxRead(int index)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
// Here we get the min/max value of the truncated position of the upscaled framebuffer.
|
|
|
|
// So we have to correct them to the unscaled EFB sizes.
|
|
|
|
int value = BBox::Get(index);
|
|
|
|
|
|
|
|
if (index < 2)
|
|
|
|
{
|
|
|
|
// left/right
|
2017-03-04 06:42:21 +00:00
|
|
|
value = value * EFB_WIDTH / m_target_width;
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// up/down
|
2017-03-04 06:42:21 +00:00
|
|
|
value = value * EFB_HEIGHT / m_target_height;
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
if (index & 1)
|
|
|
|
value++; // fix max values to describe the outer border
|
|
|
|
|
|
|
|
return value;
|
2014-12-05 02:01:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void Renderer::BBoxWrite(int index, u16 _value)
|
|
|
|
{
|
2016-06-24 08:43:46 +00:00
|
|
|
int value = _value; // u16 isn't enough to multiply by the efb width
|
|
|
|
if (index & 1)
|
|
|
|
value--;
|
|
|
|
if (index < 2)
|
|
|
|
{
|
2017-03-04 06:42:21 +00:00
|
|
|
value = value * m_target_width / EFB_WIDTH;
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-03-04 06:42:21 +00:00
|
|
|
value = value * m_target_height / EFB_HEIGHT;
|
2016-06-24 08:43:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
BBox::Set(index, value);
|
2014-12-05 02:01:20 +00:00
|
|
|
}
|
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
void Renderer::Flush()
|
|
|
|
{
|
|
|
|
D3D::context->Flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Renderer::WaitForGPUIdle()
|
|
|
|
{
|
|
|
|
// There is no glFinish() equivalent in D3D.
|
|
|
|
D3D::context->Flush();
|
|
|
|
}
|
|
|
|
|
2018-11-28 04:30:47 +00:00
|
|
|
void Renderer::RenderXFBToScreen(const AbstractTexture* texture, const EFBRectangle& rc)
|
2014-12-20 17:20:49 +00:00
|
|
|
{
|
2019-02-15 01:59:50 +00:00
|
|
|
if (g_ActiveConfig.stereo_mode != StereoMode::Nvidia3DVision)
|
|
|
|
return ::Renderer::RenderXFBToScreen(texture, rc);
|
2018-11-28 04:30:47 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
if (!m_3d_vision_texture)
|
|
|
|
Create3DVisionTexture(m_backbuffer_width, m_backbuffer_height);
|
2018-11-28 04:30:47 +00:00
|
|
|
|
2019-02-15 01:59:50 +00:00
|
|
|
// Render to staging texture which is double the width of the backbuffer
|
|
|
|
SetAndClearFramebuffer(m_3d_vision_framebuffer.get());
|
|
|
|
|
|
|
|
const auto target_rc = GetTargetRectangle();
|
|
|
|
m_post_processor->BlitFromTexture(target_rc, rc, texture, 0);
|
|
|
|
m_post_processor->BlitFromTexture(
|
|
|
|
MathUtil::Rectangle<int>(target_rc.left + m_backbuffer_width, target_rc.top,
|
|
|
|
target_rc.right + m_backbuffer_width, target_rc.bottom),
|
|
|
|
rc, texture, 1);
|
|
|
|
|
|
|
|
// Copy the left eye to the backbuffer, if Nvidia 3D Vision is enabled it should
|
|
|
|
// recognize the signature and automatically include the right eye frame.
|
|
|
|
const CD3D11_BOX box(0, 0, 0, m_backbuffer_width, m_backbuffer_height, 1);
|
|
|
|
D3D::context->CopySubresourceRegion(D3D::GetSwapChainTexture()->GetD3DTexture(), 0, 0, 0, 0,
|
|
|
|
m_3d_vision_texture->GetD3DTexture(), 0, &box);
|
|
|
|
|
|
|
|
// Restore render target to backbuffer
|
|
|
|
SetFramebuffer(D3D::GetSwapChainFramebuffer());
|
2014-12-20 17:20:49 +00:00
|
|
|
}
|
|
|
|
|
2016-11-09 00:07:56 +00:00
|
|
|
void Renderer::SetFullscreen(bool enable_fullscreen)
|
|
|
|
{
|
|
|
|
D3D::SetFullscreenState(enable_fullscreen);
|
|
|
|
}
|
|
|
|
|
2016-11-13 21:16:29 +00:00
|
|
|
bool Renderer::IsFullscreen() const
|
2016-11-09 00:41:38 +00:00
|
|
|
{
|
|
|
|
return D3D::GetFullscreenState();
|
|
|
|
}
|
|
|
|
|
2012-01-06 12:45:51 +00:00
|
|
|
} // namespace DX11
|