Skip to content

Commit

Permalink
Merge pull request #10809 from libretro/master
Browse files Browse the repository at this point in the history
Libretro: add D3D11 support / fix GL context reset.
  • Loading branch information
hrydgard authored Mar 27, 2018
2 parents c637023 + bb64390 commit 29de4b5
Show file tree
Hide file tree
Showing 17 changed files with 1,082 additions and 802 deletions.
2 changes: 2 additions & 0 deletions Common/ConsoleListener.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ ConsoleListener::ConsoleListener() : bHidden(true)
bUseColor = false;
#elif PPSSPP_PLATFORM(UWP)
bUseColor = false;
#elif defined(_MSC_VER)
bUseColor = false;
#else
bUseColor = isatty(fileno(stdout));
#endif
Expand Down
30 changes: 30 additions & 0 deletions ext/native/thin3d/thin3d_d3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ class D3D11DrawContext : public DrawContext {
void DrawUP(const void *vdata, int vertexCount) override;
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal);

void BeginFrame() override;

std::string GetInfoString(InfoField info) const override {
switch (info) {
case APIVERSION: return "Direct3D 11";
Expand Down Expand Up @@ -1274,6 +1276,34 @@ void D3D11DrawContext::Clear(int mask, uint32_t colorval, float depthVal, int st
}
}

void D3D11DrawContext::BeginFrame() {
context_->OMSetRenderTargets(1, &curRenderTargetView_, curDepthStencilView_);

if (curBlend_) {
context_->OMSetBlendState(curBlend_->bs, blendFactor_, 0xFFFFFFFF);
}
if (curDepth_) {
context_->OMSetDepthStencilState(curDepth_->dss, stencilRef_);
}
if (curRaster_) {
context_->RSSetState(curRaster_->rs);
}
context_->IASetInputLayout(curInputLayout_);
context_->VSSetShader(curVS_, nullptr, 0);
context_->PSSetShader(curPS_, nullptr, 0);
context_->GSSetShader(curGS_, nullptr, 0);
if (curTopology_ != D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED) {
context_->IASetPrimitiveTopology(curTopology_);
}
if (curPipeline_) {
context_->IASetVertexBuffers(0, 1, nextVertexBuffers_, (UINT *)curPipeline_->input->strides.data(), (UINT *)nextVertexBufferOffsets_);
context_->IASetIndexBuffer(nextIndexBuffer_, DXGI_FORMAT_R32_UINT, nextIndexBufferOffset_);
if (curPipeline_->dynamicUniforms) {
context_->VSSetConstantBuffers(0, 1, &curPipeline_->dynamicUniforms);
}
}
}

void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x, int y, int z, Framebuffer *dstfb, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBit) {
D3D11Framebuffer *src = (D3D11Framebuffer *)srcfb;
D3D11Framebuffer *dst = (D3D11Framebuffer *)dstfb;
Expand Down
17 changes: 11 additions & 6 deletions libretro/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@

set(LIBRETRO_SRCS
libretro.cpp
LibretroGraphicsContext.cpp
LibretroGLContext.cpp
LibretroVulkanContext.cpp
libretro_vulkan.cpp
)
libretro.cpp
LibretroGraphicsContext.cpp
LibretroGLContext.cpp
LibretroVulkanContext.cpp
libretro_vulkan.cpp)

if(WIN32)
set(LIBRETRO_SRCS ${LIBRETRO_SRCS}
LibretroD3D11Context.cpp)
endif()

include_directories(libretro)

Expand Down
95 changes: 95 additions & 0 deletions libretro/LibretroD3D11Context.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@

#include "libretro/LibretroD3D11Context.h"
#include "thin3d/d3d11_loader.h"
#include <d3d11_1.h>

#ifdef __MINGW32__
#undef __uuidof
#define __uuidof(type) IID_##type
#endif

bool LibretroD3D11Context::Init() {
if (!LibretroHWRenderContext::Init(true))
return false;

g_Config.iGPUBackend = (int)GPUBackend::DIRECT3D11;
return true;
}

void LibretroD3D11Context::CreateDrawContext() {
if (!Libretro::environ_cb(RETRO_ENVIRONMENT_GET_HW_RENDER_INTERFACE, (void **)&d3d11_) || !d3d11_) {
ERROR_LOG(G3D, "Failed to get HW rendering interface!\n");
return;
}

if (d3d11_->interface_version != RETRO_HW_RENDER_INTERFACE_D3D11_VERSION) {
ERROR_LOG(G3D, "HW render interface mismatch, expected %u, got %u!\n", RETRO_HW_RENDER_INTERFACE_D3D11_VERSION, d3d11_->interface_version);
return;
}

ptr_D3DCompile = d3d11_->D3DCompile;

ID3D11Device1 *device1 = nullptr;
d3d11_->device->QueryInterface(__uuidof(ID3D11Device1), (void **)&device1);

ID3D11DeviceContext1 *context1 = nullptr;
d3d11_->context->QueryInterface(__uuidof(ID3D11DeviceContext1), (void **)&context1);

draw_ = Draw::T3DCreateD3D11Context(d3d11_->device, d3d11_->context, device1, context1, d3d11_->featureLevel, NULL);
}

void LibretroD3D11Context::DestroyDrawContext() {
LibretroHWRenderContext::DestroyDrawContext();
d3d11_ = nullptr;
}

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;

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;
}
}

void LibretroD3D11Context::LostBackbuffer() {
LibretroGraphicsContext::LostBackbuffer();
SRView_->Release();
SRView_ = nullptr;
RTView_->Release();
RTView_ = nullptr;
texture_->Release();
texture_ = nullptr;
}

void LibretroD3D11Context::SwapBuffers() {
ID3D11RenderTargetView *nullView = nullptr;
d3d11_->context->OMSetRenderTargets(1, &nullView, nullptr);

d3d11_->context->PSSetShaderResources(0, 1, &SRView_);
LibretroHWRenderContext::SwapBuffers();

ID3D11ShaderResourceView *nullSRV = nullptr;
d3d11_->context->PSSetShaderResources(0, 1, &nullSRV);

draw_->HandleEvent(Draw::Event::PRESENTED, 0, 0, nullptr, nullptr);
}
27 changes: 27 additions & 0 deletions libretro/LibretroD3D11Context.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#define HAVE_D3D11
#include "libretro/libretro_d3d.h"
#include "libretro/LibretroGraphicsContext.h"

class LibretroD3D11Context : public LibretroHWRenderContext {
public:
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;

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;
};
26 changes: 7 additions & 19 deletions libretro/LibretroGLContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,30 +6,18 @@

#include "libretro/LibretroGLContext.h"

bool LibretroGLContext::Init()
{
if (!LibretroHWRenderContext::Init())
bool LibretroGLContext::Init() {
if (!LibretroHWRenderContext::Init(true))
return false;

libretro_get_proc_address = hw_render_.get_proc_address;

g_Config.iGPUBackend = (int)GPUBackend::OPENGL;
return true;
}

void LibretroGLContext::Shutdown()
{
LibretroGraphicsContext::Shutdown();
libretro_get_proc_address = nullptr;
}

void LibretroGLContext::CreateDrawContext()
{
if (!glewInitDone)
{
void LibretroGLContext::CreateDrawContext() {
if (!glewInitDone) {
#if !defined(IOS) && !defined(USING_GLES2)
if (glewInit() != GLEW_OK)
{
if (glewInit() != GLEW_OK) {
ERROR_LOG(G3D, "glewInit() failed.\n");
return;
}
Expand All @@ -40,8 +28,8 @@ void LibretroGLContext::CreateDrawContext()
draw_ = Draw::T3DCreateGLContext();
renderManager_ = (GLRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
}
void LibretroGLContext::DestroyDrawContext()
{

void LibretroGLContext::DestroyDrawContext() {
LibretroHWRenderContext::DestroyDrawContext();
renderManager_ = nullptr;
}
18 changes: 7 additions & 11 deletions libretro/LibretroGLContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,39 @@
#include "thin3d/GLRenderManager.h"

class LibretroGLContext : public LibretroHWRenderContext {
public:
public:
LibretroGLContext()
:
#ifdef USING_GLES2
HWRenderContext(RETRO_HW_CONTEXT_OPENGLES2)
: HWRenderContext(RETRO_HW_CONTEXT_OPENGLES2)
#elif defined(HAVE_OPENGL_CORE)
HWRenderContext(RETRO_HW_CONTEXT_OPENGL_CORE, 3, 1)
: HWRenderContext(RETRO_HW_CONTEXT_OPENGL_CORE, 3, 1)
#else
LibretroHWRenderContext(RETRO_HW_CONTEXT_OPENGL)
: LibretroHWRenderContext(RETRO_HW_CONTEXT_OPENGL)
#endif
{
hw_render_.bottom_left_origin = true;
}

bool Init() override;
void Shutdown() override;
void CreateDrawContext() override;
void DestroyDrawContext() override;
void SetRenderTarget() override
{
void SetRenderTarget() override {
extern GLuint g_defaultFBO;
g_defaultFBO = hw_render_.get_current_framebuffer();
}

void ThreadStart() override { renderManager_->ThreadStart(); }
bool ThreadFrame() override { return renderManager_->ThreadFrame(); }
void ThreadEnd() override { renderManager_->ThreadEnd(); }
void StopThread() override
{
void StopThread() override {
renderManager_->WaitUntilQueueIdle();
renderManager_->StopThread();
}

GPUCore GetGPUCore() override { return GPUCORE_GLES; }
const char *Ident() override { return "OpenGL"; }

private:
private:
GLRenderManager *renderManager_ = nullptr;
bool glewInitDone = false;
};
Loading

0 comments on commit 29de4b5

Please sign in to comment.