mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
libretro: D3D11 backend crash fix and comments
This commit is contained in:
parent
81015abef7
commit
2d598747b5
2 changed files with 101 additions and 76 deletions
|
@ -12,95 +12,118 @@
|
|||
#endif
|
||||
|
||||
bool LibretroD3D11Context::Init() {
|
||||
if (!LibretroHWRenderContext::Init(true))
|
||||
return false;
|
||||
if (!LibretroHWRenderContext::Init(true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
|
||||
return true;
|
||||
g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LibretroD3D11Context::CreateDrawContext() {
|
||||
std::vector<std::string> adapterNames;
|
||||
retro_hw_render_interface_d3d11 *d3d11Interface = nullptr;
|
||||
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&d3d11Interface) || !d3d11Interface) {
|
||||
ERROR_LOG(Log::G3D, "Failed to get HW rendering interface!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&d3d11_) || !d3d11_) {
|
||||
ERROR_LOG(Log::G3D, "Failed to get HW rendering interface!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (d3d11_->interface_version != RETRO_HW_RENDER_INTERFACE_D3D11_VERSION) {
|
||||
ERROR_LOG(Log::G3D, "HW render interface mismatch, expected %u, got %u!\n", RETRO_HW_RENDER_INTERFACE_D3D11_VERSION, d3d11_->interface_version);
|
||||
return;
|
||||
}
|
||||
if (d3d11Interface->interface_version != RETRO_HW_RENDER_INTERFACE_D3D11_VERSION) {
|
||||
ERROR_LOG(Log::G3D, "HW render interface mismatch, expected %u, got %u!\n", RETRO_HW_RENDER_INTERFACE_D3D11_VERSION, d3d11Interface->interface_version);
|
||||
return;
|
||||
}
|
||||
|
||||
// Reject lower feature levels. We have D3D9 for these ancient GPUs.
|
||||
if (d3d11_->featureLevel < D3D_FEATURE_LEVEL_10_0) {
|
||||
if (d3d11Interface->featureLevel < D3D_FEATURE_LEVEL_10_0) {
|
||||
ERROR_LOG(Log::G3D, "D3D11 featureLevel not high enough - rejecting!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ptr_D3DCompile = d3d11_->D3DCompile;
|
||||
// Workaround: RetroArch doesn't correctly persist interface pointers across context_reset calls even
|
||||
// with cache_context set. Pointers within the structure are persisted. Make a hard copy instead to
|
||||
// avoid crashes.
|
||||
hwInterface_ = *d3d11Interface;
|
||||
|
||||
ID3D11Device1 *device1 = nullptr;
|
||||
d3d11_->device->QueryInterface(__uuidof(ID3D11Device1), (void **)&device1);
|
||||
ptr_D3DCompile = hwInterface_.D3DCompile;
|
||||
hwInterface_.device->QueryInterface(__uuidof(ID3D11Device1), (void **)&device1_);
|
||||
hwInterface_.context->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&context1_);
|
||||
|
||||
ID3D11DeviceContext1 *context1 = nullptr;
|
||||
d3d11_->context->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&context1);
|
||||
|
||||
draw_ = Draw::T3DCreateD3D11Context(d3d11_->device, d3d11_->context, device1, context1, nullptr, d3d11_->featureLevel, NULL, adapterNames, 3);
|
||||
std::vector<std::string> adapterNames;
|
||||
draw_ = Draw::T3DCreateD3D11Context(hwInterface_.device, hwInterface_.context, device1_, context1_, nullptr, hwInterface_.featureLevel, nullptr, adapterNames, g_Config.iInflightFrames);
|
||||
}
|
||||
|
||||
void LibretroD3D11Context::DestroyDrawContext() {
|
||||
LibretroHWRenderContext::DestroyDrawContext();
|
||||
d3d11_ = nullptr;
|
||||
LibretroHWRenderContext::DestroyDrawContext();
|
||||
if (device1_) {
|
||||
device1_->Release();
|
||||
device1_ = nullptr;
|
||||
}
|
||||
if (context1_) {
|
||||
context1_->Release();
|
||||
context1_ = nullptr;
|
||||
}
|
||||
hwInterface_ = {};
|
||||
}
|
||||
|
||||
void LibretroD3D11Context::GotBackbuffer() {
|
||||
D3D11_TEXTURE2D_DESC desc{};
|
||||
desc.Width = PSP_CoreParameter().pixelWidth;
|
||||
desc.Height = PSP_CoreParameter().pixelHeight;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = format_;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
D3D11_TEXTURE2D_DESC desc{};
|
||||
desc.Width = PSP_CoreParameter().pixelWidth;
|
||||
desc.Height = PSP_CoreParameter().pixelHeight;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = format_;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.Usage = D3D11_USAGE_DEFAULT;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = 0;
|
||||
|
||||
if (SUCCEEDED(d3d11_->device->CreateTexture2D(&desc, nullptr, &texture_))) {
|
||||
if (SUCCEEDED(d3d11_->device->CreateRenderTargetView(texture_, nullptr, &RTView_))) {
|
||||
if (SUCCEEDED(d3d11_->device->CreateShaderResourceView(texture_, nullptr, &SRView_))) {
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight, RTView_, texture_);
|
||||
return;
|
||||
}
|
||||
RTView_->Release();
|
||||
RTView_ = nullptr;
|
||||
}
|
||||
texture_->Release();
|
||||
texture_ = nullptr;
|
||||
}
|
||||
if (SUCCEEDED(hwInterface_.device->CreateTexture2D(&desc, nullptr, &texture_))) {
|
||||
if (SUCCEEDED(hwInterface_.device->CreateRenderTargetView(texture_, nullptr, &texture_rt_view_))) {
|
||||
if (SUCCEEDED(hwInterface_.device->CreateShaderResourceView(texture_, nullptr, &texture_sr_view_))) {
|
||||
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, desc.Width, desc.Height, texture_rt_view_, texture_);
|
||||
return;
|
||||
}
|
||||
texture_rt_view_->Release();
|
||||
texture_rt_view_ = nullptr;
|
||||
}
|
||||
texture_->Release();
|
||||
texture_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LibretroD3D11Context::LostBackbuffer() {
|
||||
LibretroGraphicsContext::LostBackbuffer();
|
||||
SRView_->Release();
|
||||
SRView_ = nullptr;
|
||||
RTView_->Release();
|
||||
RTView_ = nullptr;
|
||||
texture_->Release();
|
||||
texture_ = nullptr;
|
||||
if (draw_ && texture_) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture_->GetDesc(&desc);
|
||||
|
||||
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, desc.Width, desc.Height);
|
||||
}
|
||||
if (texture_sr_view_) {
|
||||
texture_sr_view_->Release();
|
||||
texture_sr_view_ = nullptr;
|
||||
}
|
||||
if (texture_rt_view_) {
|
||||
texture_rt_view_->Release();
|
||||
texture_rt_view_ = nullptr;
|
||||
}
|
||||
if (texture_) {
|
||||
texture_->Release();
|
||||
texture_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void LibretroD3D11Context::SwapBuffers() {
|
||||
ID3D11RenderTargetView *nullView = nullptr;
|
||||
d3d11_->context->OMSetRenderTargets(1, &nullView, nullptr);
|
||||
ID3D11RenderTargetView *nullView = nullptr;
|
||||
hwInterface_.context->OMSetRenderTargets(1, &nullView, nullptr);
|
||||
|
||||
d3d11_->context->PSSetShaderResources(0, 1, &SRView_);
|
||||
LibretroHWRenderContext::SwapBuffers();
|
||||
// libretro doesn't specify how to pass our D3D11 frame to the frontend. RetroArch expects it to be
|
||||
// bound to the first shader resource slot.
|
||||
hwInterface_.context->PSSetShaderResources(0, 1, &texture_sr_view_);
|
||||
LibretroHWRenderContext::SwapBuffers();
|
||||
|
||||
ID3D11ShaderResourceView *nullSRV = nullptr;
|
||||
d3d11_->context->PSSetShaderResources(0, 1, &nullSRV);
|
||||
ID3D11ShaderResourceView *nullSRV = nullptr;
|
||||
hwInterface_.context->PSSetShaderResources(0, 1, &nullSRV);
|
||||
|
||||
draw_->HandleEvent(Draw::Event::PRESENTED, 0, 0, nullptr, nullptr);
|
||||
draw_->HandleEvent(Draw::Event::PRESENTED, 0, 0, nullptr, nullptr);
|
||||
}
|
||||
|
|
|
@ -6,22 +6,24 @@
|
|||
|
||||
class LibretroD3D11Context : public LibretroHWRenderContext {
|
||||
public:
|
||||
LibretroD3D11Context() : LibretroHWRenderContext(RETRO_HW_CONTEXT_DIRECT3D, 11) {}
|
||||
bool Init() override;
|
||||
LibretroD3D11Context() : LibretroHWRenderContext(RETRO_HW_CONTEXT_DIRECT3D, 11) {}
|
||||
bool Init() override;
|
||||
|
||||
void SwapBuffers() override;
|
||||
void GotBackbuffer() override;
|
||||
void LostBackbuffer() override;
|
||||
void CreateDrawContext() override;
|
||||
void DestroyDrawContext() override;
|
||||
void SwapBuffers() override;
|
||||
void GotBackbuffer() override;
|
||||
void LostBackbuffer() override;
|
||||
void CreateDrawContext() override;
|
||||
void DestroyDrawContext() override;
|
||||
|
||||
GPUCore GetGPUCore() override { return GPUCORE_DIRECTX11; }
|
||||
const char *Ident() override { return "DirectX 11"; }
|
||||
GPUCore GetGPUCore() override { return GPUCORE_DIRECTX11; }
|
||||
const char *Ident() override { return "DirectX 11"; }
|
||||
|
||||
private:
|
||||
retro_hw_render_interface_d3d11 *d3d11_ = nullptr;
|
||||
ID3D11Texture2D *texture_ = nullptr;
|
||||
ID3D11RenderTargetView *RTView_ = nullptr;
|
||||
ID3D11ShaderResourceView *SRView_ = nullptr;
|
||||
DXGI_FORMAT format_ = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
retro_hw_render_interface_d3d11 hwInterface_ = {};
|
||||
ID3D11Device1 *device1_ = nullptr;
|
||||
ID3D11DeviceContext1 *context1_ = nullptr;
|
||||
ID3D11Texture2D *texture_ = nullptr;
|
||||
ID3D11RenderTargetView *texture_rt_view_ = nullptr;
|
||||
ID3D11ShaderResourceView *texture_sr_view_ = nullptr;
|
||||
DXGI_FORMAT format_ = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
};
|
||||
|
|
Loading…
Add table
Reference in a new issue