Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/libretro/LibretroD3D11Context.cpp
3185 views
1
#include "Common/Log.h"
2
#include "Core/Config.h"
3
#include "Core/ConfigValues.h"
4
#include "libretro/LibretroD3D11Context.h"
5
#include "Common/GPU/D3D11/D3D11Loader.h"
6
7
#include <d3d11_1.h>
8
9
#ifdef __MINGW32__
10
#undef __uuidof
11
#define __uuidof(type) IID_##type
12
#endif
13
14
bool LibretroD3D11Context::Init() {
15
if (!LibretroHWRenderContext::Init(true)) {
16
return false;
17
}
18
19
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
20
return true;
21
}
22
23
void LibretroD3D11Context::CreateDrawContext() {
24
retro_hw_render_interface_d3d11 *d3d11Interface = nullptr;
25
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&d3d11Interface)) {
26
ERROR_LOG(Log::G3D, "Failed to get HW rendering interface!\n");
27
return;
28
}
29
30
if (!d3d11Interface) {
31
ERROR_LOG(Log::G3D, "D3D11 interface was null!\n");
32
return;
33
}
34
35
if (d3d11Interface->interface_version != RETRO_HW_RENDER_INTERFACE_D3D11_VERSION) {
36
ERROR_LOG(Log::G3D, "HW render interface mismatch, expected %u, got %u!\n", RETRO_HW_RENDER_INTERFACE_D3D11_VERSION, d3d11Interface->interface_version);
37
return;
38
}
39
40
// Reject lower feature levels. We have D3D9 for these ancient GPUs.
41
if (d3d11Interface->featureLevel < D3D_FEATURE_LEVEL_10_0) {
42
ERROR_LOG(Log::G3D, "D3D11 featureLevel not high enough - rejecting!\n");
43
return;
44
}
45
46
// Workaround: RetroArch doesn't correctly persist interface pointers across context_reset calls even
47
// with cache_context set. Pointers within the structure are persisted. Make a hard copy instead to
48
// avoid crashes.
49
hwInterface_ = *d3d11Interface;
50
51
ptr_D3DCompile = hwInterface_.D3DCompile;
52
hwInterface_.device->QueryInterface(__uuidof(ID3D11Device1), (void **)&device1_);
53
hwInterface_.context->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&context1_);
54
55
std::vector<std::string> adapterNames;
56
draw_ = Draw::T3DCreateD3D11Context(hwInterface_.device, hwInterface_.context, device1_, context1_, nullptr, hwInterface_.featureLevel, nullptr, adapterNames, g_Config.iInflightFrames);
57
}
58
59
void LibretroD3D11Context::DestroyDrawContext() {
60
LibretroHWRenderContext::DestroyDrawContext();
61
if (device1_) {
62
device1_->Release();
63
device1_ = nullptr;
64
}
65
if (context1_) {
66
context1_->Release();
67
context1_ = nullptr;
68
}
69
hwInterface_ = {};
70
}
71
72
void LibretroD3D11Context::GotBackbuffer() {
73
D3D11_TEXTURE2D_DESC desc{};
74
desc.Width = PSP_CoreParameter().pixelWidth;
75
desc.Height = PSP_CoreParameter().pixelHeight;
76
desc.MipLevels = 1;
77
desc.ArraySize = 1;
78
desc.Format = format_;
79
desc.SampleDesc.Count = 1;
80
desc.SampleDesc.Quality = 0;
81
desc.Usage = D3D11_USAGE_DEFAULT;
82
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
83
desc.CPUAccessFlags = 0;
84
desc.MiscFlags = 0;
85
86
if (SUCCEEDED(hwInterface_.device->CreateTexture2D(&desc, nullptr, &texture_))) {
87
if (SUCCEEDED(hwInterface_.device->CreateRenderTargetView(texture_, nullptr, &texture_rt_view_))) {
88
if (SUCCEEDED(hwInterface_.device->CreateShaderResourceView(texture_, nullptr, &texture_sr_view_))) {
89
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, desc.Width, desc.Height, texture_rt_view_, texture_);
90
return;
91
}
92
texture_rt_view_->Release();
93
texture_rt_view_ = nullptr;
94
}
95
texture_->Release();
96
texture_ = nullptr;
97
}
98
}
99
100
void LibretroD3D11Context::LostBackbuffer() {
101
if (draw_ && texture_) {
102
D3D11_TEXTURE2D_DESC desc;
103
texture_->GetDesc(&desc);
104
105
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, desc.Width, desc.Height);
106
}
107
if (texture_sr_view_) {
108
texture_sr_view_->Release();
109
texture_sr_view_ = nullptr;
110
}
111
if (texture_rt_view_) {
112
texture_rt_view_->Release();
113
texture_rt_view_ = nullptr;
114
}
115
if (texture_) {
116
texture_->Release();
117
texture_ = nullptr;
118
}
119
}
120
121
void LibretroD3D11Context::SwapBuffers() {
122
ID3D11RenderTargetView *nullView = nullptr;
123
hwInterface_.context->OMSetRenderTargets(1, &nullView, nullptr);
124
125
// libretro doesn't specify how to pass our D3D11 frame to the frontend. RetroArch expects it to be
126
// bound to the first shader resource slot.
127
hwInterface_.context->PSSetShaderResources(0, 1, &texture_sr_view_);
128
LibretroHWRenderContext::SwapBuffers();
129
130
ID3D11ShaderResourceView *nullSRV = nullptr;
131
hwInterface_.context->PSSetShaderResources(0, 1, &nullSRV);
132
133
draw_->HandleEvent(Draw::Event::PRESENTED, 0, 0, nullptr, nullptr);
134
}
135
136