Libretro: add experimental D3D11 support.

This commit is contained in:
aliaspider 2018-03-25 23:07:02 +01:00
parent 4d1503666a
commit 808bf8e681
9 changed files with 260 additions and 28 deletions

View File

@ -98,6 +98,8 @@ public:
void DrawUP(const void *vdata, int vertexCount) override; void DrawUP(const void *vdata, int vertexCount) override;
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal); void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal);
void BeginFrame() override;
std::string GetInfoString(InfoField info) const override { std::string GetInfoString(InfoField info) const override {
switch (info) { switch (info) {
case APIVERSION: return "Direct3D 11"; case APIVERSION: return "Direct3D 11";
@ -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) { 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 *src = (D3D11Framebuffer *)srcfb;
D3D11Framebuffer *dst = (D3D11Framebuffer *)dstfb; D3D11Framebuffer *dst = (D3D11Framebuffer *)dstfb;

View File

@ -1,10 +1,15 @@
set(LIBRETRO_SRCS set(LIBRETRO_SRCS
libretro.cpp libretro.cpp
LibretroGraphicsContext.cpp LibretroGraphicsContext.cpp
LibretroGLContext.cpp LibretroGLContext.cpp
LibretroVulkanContext.cpp LibretroVulkanContext.cpp
libretro_vulkan.cpp libretro_vulkan.cpp)
)
if(WIN32)
set(LIBRETRO_SRCS ${LIBRETRO_SRCS}
LibretroD3D11Context.cpp)
endif()
include_directories(libretro) include_directories(libretro)

View File

@ -0,0 +1,104 @@
#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())
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::ContextDestroy()
{
LibretroHWRenderContext::ContextDestroy();
#if 0
// this should be enabled once DeviceLost/DeviceRestore can fully switch to a new draw context.
DestroyDrawContext();
#endif
}
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);
}

View File

@ -0,0 +1,28 @@
#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;
void ContextDestroy() 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;
};

View File

@ -5,6 +5,9 @@
#ifndef NO_VULKAN #ifndef NO_VULKAN
#include "libretro/LibretroVulkanContext.h" #include "libretro/LibretroVulkanContext.h"
#endif #endif
#ifdef _WIN32
#include "libretro/LibretroD3D11Context.h"
#endif
#include "Common/Log.h" #include "Common/Log.h"
#include "Core/Config.h" #include "Core/Config.h"
@ -34,8 +37,8 @@ void LibretroHWRenderContext::ContextReset()
{ {
INFO_LOG(G3D, "Context reset"); INFO_LOG(G3D, "Context reset");
// needed to restart the thread // needed to restart the thread
// TODO: find a way to move this to ContextDestroy. // TODO: find a way to move this to ContextDestroy.
if (Libretro::useEmuThread && draw_ && Libretro::emuThreadState != Libretro::EmuThreadState::PAUSED) if (Libretro::useEmuThread && draw_ && Libretro::emuThreadState != Libretro::EmuThreadState::PAUSED)
DestroyDrawContext(); DestroyDrawContext();
@ -43,10 +46,12 @@ void LibretroHWRenderContext::ContextReset()
{ {
CreateDrawContext(); CreateDrawContext();
PSP_CoreParameter().thin3d = draw_; PSP_CoreParameter().thin3d = draw_;
draw_->CreatePresets(); bool success = draw_->CreatePresets();
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); assert(success);
} }
GotBackbuffer();
if (gpu) if (gpu)
gpu->DeviceRestore(); gpu->DeviceRestore();
} }
@ -64,9 +69,20 @@ void LibretroHWRenderContext::ContextDestroy()
#endif #endif
} }
LostBackbuffer();
gpu->DeviceLost(); gpu->DeviceLost();
} }
void LibretroGraphicsContext::GotBackbuffer()
{
draw_->HandleEvent(Draw::Event::GOT_BACKBUFFER, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
}
void LibretroGraphicsContext::LostBackbuffer()
{
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, -1, -1);
}
LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext() LibretroGraphicsContext *LibretroGraphicsContext::CreateGraphicsContext()
{ {
LibretroGraphicsContext *ctx; LibretroGraphicsContext *ctx;

View File

@ -11,7 +11,7 @@
class LibretroGraphicsContext : public GraphicsContext { class LibretroGraphicsContext : public GraphicsContext {
public: public:
LibretroGraphicsContext() {} LibretroGraphicsContext() {}
~LibretroGraphicsContext() override {} ~LibretroGraphicsContext() override { Shutdown();}
virtual bool Init() = 0; virtual bool Init() = 0;
virtual void SetRenderTarget() {} virtual void SetRenderTarget() {}
@ -26,12 +26,14 @@ class LibretroGraphicsContext : public GraphicsContext {
void SwapInterval(int interval) override {} void SwapInterval(int interval) override {}
void Resize() override {} void Resize() override {}
virtual void GotBackbuffer();
virtual void LostBackbuffer();
virtual void CreateDrawContext() {} virtual void CreateDrawContext() {}
virtual void DestroyDrawContext() virtual void DestroyDrawContext()
{ {
if (!draw_) if (!draw_)
return; return;
draw_->HandleEvent(Draw::Event::LOST_BACKBUFFER, -1, -1);
delete draw_; delete draw_;
draw_ = nullptr; draw_ = nullptr;
} }
@ -81,21 +83,6 @@ class LibretroD3D9Context : public LibretroHWRenderContext {
GPUCore GetGPUCore() override { return GPUCORE_DIRECTX9; } GPUCore GetGPUCore() override { return GPUCORE_DIRECTX9; }
const char *Ident() override { return "DirectX 9"; } const char *Ident() override { return "DirectX 9"; }
}; };
class LibretroD3D11Context : public LibretroHWRenderContext {
public:
LibretroD3D11Context() : LibretroHWRenderContext(RETRO_HW_CONTEXT_DIRECT3D, 11) {}
bool Init() override { return false; }
void CreateDrawContext() override
{
draw_ = Draw::T3DCreateD3D11Context(nullptr, nullptr, nullptr, nullptr, D3D_FEATURE_LEVEL_11_0, nullptr);
draw_->CreatePresets();
}
GPUCore GetGPUCore() override { return GPUCORE_DIRECTX11; }
const char *Ident() override { return "DirectX 11"; }
};
#endif #endif
class LibretroSoftwareContext : public LibretroGraphicsContext { class LibretroSoftwareContext : public LibretroGraphicsContext {

View File

@ -636,7 +636,8 @@ SOURCES_CXX += \
$(GPUDIR)/D3D11/StencilBufferD3D11.cpp \ $(GPUDIR)/D3D11/StencilBufferD3D11.cpp \
$(GPUDIR)/D3D11/TextureCacheD3D11.cpp \ $(GPUDIR)/D3D11/TextureCacheD3D11.cpp \
$(GPUDIR)/D3D11/TextureScalerD3D11.cpp \ $(GPUDIR)/D3D11/TextureScalerD3D11.cpp \
$(GPUDIR)/D3D11/VertexShaderGeneratorD3D11.cpp $(GPUDIR)/D3D11/VertexShaderGeneratorD3D11.cpp \
$(LIBRETRODIR)/LibretroD3D11Context.cpp
SOURCES_CXX += \ SOURCES_CXX += \
$(NATIVEDIR)/thin3d/thin3d_d3d9.cpp \ $(NATIVEDIR)/thin3d/thin3d_d3d9.cpp \

View File

@ -3,6 +3,7 @@
#include <cassert> #include <cassert>
#include <thread> #include <thread>
#include <atomic> #include <atomic>
#include <vector>
#include "base/timeutil.h" #include "base/timeutil.h"
#include "Common/ChunkFile.h" #include "Common/ChunkFile.h"

60
libretro/libretro_d3d.h Normal file
View File

@ -0,0 +1,60 @@
/* Copyright (C) 2010-2016 The RetroArch team
*
* ---------------------------------------------------------------------------------------------
* The following license statement only applies to this libretro API header (libretro_vulkan.h)
* ---------------------------------------------------------------------------------------------
*
* Permission is hereby granted, free of charge,
* to any person obtaining a copy of this software and associated documentation files (the
* "Software"),
* to deal in the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef LIBRETRO_DIRECT3D_H__
#define LIBRETRO_DIRECT3D_H__
#include "libretro.h"
#ifdef HAVE_D3D11
#include <d3d11.h>
#include <D3Dcompiler.h>
#define RETRO_HW_RENDER_INTERFACE_D3D11_VERSION 1
struct retro_hw_render_interface_d3d11
{
/* Must be set to RETRO_HW_RENDER_INTERFACE_D3D11. */
enum retro_hw_render_interface_type interface_type;
/* Must be set to RETRO_HW_RENDER_INTERFACE_D3D11_VERSION. */
unsigned interface_version;
/* Opaque handle to the d3d11 backend in the frontend
* which must be passed along to all function pointers
* in this interface.
*/
void* handle;
ID3D11Device *device;
ID3D11DeviceContext *context;
D3D_FEATURE_LEVEL featureLevel;
pD3DCompile D3DCompile;
};
#endif
#endif /* LIBRETRO_DIRECT3D_H__ */