2017-02-08 18:07:34 +01:00
// Copyright (c) 2017- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
2020-05-10 17:14:20 -07:00
# include <algorithm>
2017-02-23 11:26:16 +01:00
# include <d3d11.h>
# include <D3Dcompiler.h>
2017-03-07 13:00:59 +01:00
# include "base/display.h"
2017-02-08 18:07:34 +01:00
# include "math/lin/matrix4x4.h"
# include "ext/native/thin3d/thin3d.h"
2017-02-12 11:20:55 +01:00
# include "base/basictypes.h"
2017-02-08 18:07:34 +01:00
# include "Common/ColorConv.h"
2017-02-16 16:37:34 +01:00
# include "Common/MathUtil.h"
2017-02-08 18:07:34 +01:00
# include "Core/MemMap.h"
# include "Core/Config.h"
2018-06-16 18:42:31 -07:00
# include "Core/ConfigValues.h"
2017-02-08 18:07:34 +01:00
# include "Core/System.h"
# include "Core/Reporting.h"
# include "GPU/ge_constants.h"
# include "GPU/GPUState.h"
# include "GPU/Debugger/Stepping.h"
# include "GPU/Common/FramebufferCommon.h"
2020-05-09 22:06:22 -07:00
# include "GPU/Common/PresentationCommon.h"
2017-02-16 16:37:34 +01:00
# include "GPU/Common/ShaderTranslation.h"
2017-02-08 18:07:34 +01:00
# include "GPU/Common/TextureDecoder.h"
# include "GPU/D3D11/FramebufferManagerD3D11.h"
# include "GPU/D3D11/ShaderManagerD3D11.h"
# include "GPU/D3D11/TextureCacheD3D11.h"
# include "GPU/D3D11/DrawEngineD3D11.h"
# ifdef _M_SSE
2017-03-12 17:16:38 +01:00
# include <emmintrin.h>
2017-02-08 18:07:34 +01:00
# endif
2017-02-12 11:20:55 +01:00
static const char * vscode =
2017-02-08 18:07:34 +01:00
" struct VS_IN { \n "
" float4 ObjPos : POSITION; \n "
" float2 Uv : TEXCOORD0; \n "
" }; "
" struct VS_OUT { \n "
" float2 Uv : TEXCOORD0; \n "
2017-02-10 00:01:56 +01:00
" float4 ProjPos : SV_Position; \n "
2017-02-08 18:07:34 +01:00
" }; \n "
" VS_OUT main(VS_IN In) { \n "
" VS_OUT Out; \n "
" Out.ProjPos = In.ObjPos; \n "
" Out.Uv = In.Uv; \n "
" return Out; \n "
" } \n " ;
2017-02-12 11:20:55 +01:00
static const char * pscode =
2017-02-08 18:07:34 +01:00
" SamplerState samp : register(s0); \n "
" Texture2D<float4> tex : register(t0); \n "
" struct PS_IN { \n "
" float2 Uv : TEXCOORD0; \n "
" }; \n "
" float4 main( PS_IN In ) : SV_Target { \n "
" float4 c = tex.Sample(samp, In.Uv); \n "
" return c; \n "
" } \n " ;
2017-02-12 13:55:49 +01:00
const D3D11_INPUT_ELEMENT_DESC FramebufferManagerD3D11 : : g_QuadVertexElements [ 2 ] = {
2017-02-08 18:07:34 +01:00
{ " POSITION " , 0 , DXGI_FORMAT_R32G32B32_FLOAT , 0 , 0 , } ,
{ " TEXCOORD " , 0 , DXGI_FORMAT_R32G32_FLOAT , 0 , 12 , } ,
} ;
FramebufferManagerD3D11 : : FramebufferManagerD3D11 ( Draw : : DrawContext * draw )
2017-02-12 13:55:49 +01:00
: FramebufferManagerCommon ( draw ) {
2017-02-08 18:07:34 +01:00
device_ = ( ID3D11Device * ) draw - > GetNativeObject ( Draw : : NativeObject : : DEVICE ) ;
context_ = ( ID3D11DeviceContext * ) draw - > GetNativeObject ( Draw : : NativeObject : : CONTEXT ) ;
2017-03-05 12:26:46 +01:00
featureLevel_ = ( D3D_FEATURE_LEVEL ) draw - > GetNativeObject ( Draw : : NativeObject : : FEATURE_LEVEL ) ;
2017-02-08 18:07:34 +01:00
std : : vector < uint8_t > bytecode ;
std : : string errorMsg ;
2017-03-05 12:26:46 +01:00
quadVertexShader_ = CreateVertexShaderD3D11 ( device_ , vscode , strlen ( vscode ) , & bytecode , featureLevel_ ) ;
quadPixelShader_ = CreatePixelShaderD3D11 ( device_ , pscode , strlen ( pscode ) , featureLevel_ ) ;
2017-03-05 10:33:35 +01:00
ASSERT_SUCCESS ( device_ - > CreateInputLayout ( g_QuadVertexElements , ARRAY_SIZE ( g_QuadVertexElements ) , bytecode . data ( ) , bytecode . size ( ) , & quadInputLayout_ ) ) ;
2017-02-12 11:20:55 +01:00
// STRIP geometry
static const float fsCoord [ 20 ] = {
- 1.0f , - 1.0f , 0.0f , 0.0f , 0.0f ,
1.0f , - 1.0f , 0.0f , 1.0f , 0.0f ,
- 1.0f , 1.0f , 0.0f , 0.0f , 1.0f ,
1.0f , 1.0f , 0.0f , 1.0f , 1.0f ,
2017-02-08 18:07:34 +01:00
} ;
D3D11_BUFFER_DESC vb { } ;
vb . ByteWidth = 20 * 4 ;
vb . Usage = D3D11_USAGE_IMMUTABLE ;
vb . CPUAccessFlags = 0 ;
2017-02-12 11:20:55 +01:00
vb . BindFlags = D3D11_BIND_VERTEX_BUFFER ;
D3D11_SUBRESOURCE_DATA data { fsCoord } ;
2017-03-05 10:33:35 +01:00
ASSERT_SUCCESS ( device_ - > CreateBuffer ( & vb , & data , & fsQuadBuffer_ ) ) ;
2017-02-12 11:20:55 +01:00
vb . Usage = D3D11_USAGE_DYNAMIC ;
vb . CPUAccessFlags = D3D11_CPU_ACCESS_WRITE ;
2017-03-05 10:33:35 +01:00
ASSERT_SUCCESS ( device_ - > CreateBuffer ( & vb , nullptr , & quadBuffer_ ) ) ;
2017-02-16 16:37:34 +01:00
2018-08-30 21:00:21 -07:00
D3D11_TEXTURE2D_DESC desc { } ;
desc . CPUAccessFlags = 0 ;
desc . Usage = D3D11_USAGE_DEFAULT ;
desc . ArraySize = 1 ;
desc . SampleDesc . Count = 1 ;
desc . Width = 1 ;
desc . Height = 1 ;
desc . Format = DXGI_FORMAT_B8G8R8A8_UNORM ;
desc . MipLevels = 1 ;
desc . BindFlags = D3D11_BIND_SHADER_RESOURCE ;
ASSERT_SUCCESS ( device_ - > CreateTexture2D ( & desc , nullptr , & nullTexture_ ) ) ;
ASSERT_SUCCESS ( device_ - > CreateShaderResourceView ( nullTexture_ , nullptr , & nullTextureView_ ) ) ;
uint32_t nullData [ 1 ] { } ;
context_ - > UpdateSubresource ( nullTexture_ , 0 , nullptr , nullData , 1 , 0 ) ;
2017-02-16 16:37:34 +01:00
ShaderTranslationInit ( ) ;
2020-05-10 16:53:15 -07:00
presentation_ - > SetLanguage ( HLSL_D3D11 ) ;
2020-05-11 13:36:23 -07:00
preferredPixelsFormat_ = Draw : : DataFormat : : B8G8R8A8_UNORM ;
2017-02-08 18:07:34 +01:00
}
FramebufferManagerD3D11 : : ~ FramebufferManagerD3D11 ( ) {
2017-02-16 16:37:34 +01:00
ShaderTranslationShutdown ( ) ;
2017-02-09 13:27:45 +01:00
// Drawing cleanup
2017-02-12 13:55:49 +01:00
if ( quadVertexShader_ )
2017-02-12 11:20:55 +01:00
quadVertexShader_ - > Release ( ) ;
2017-02-12 13:55:49 +01:00
if ( quadPixelShader_ )
2017-02-12 11:20:55 +01:00
quadPixelShader_ - > Release ( ) ;
2017-02-12 13:55:49 +01:00
quadInputLayout_ - > Release ( ) ;
2017-02-12 11:20:55 +01:00
quadBuffer_ - > Release ( ) ;
fsQuadBuffer_ - > Release ( ) ;
2017-02-09 13:27:45 +01:00
// Stencil cleanup
for ( int i = 0 ; i < 256 ; i + + ) {
if ( stencilMaskStates_ [ i ] )
stencilMaskStates_ [ i ] - > Release ( ) ;
}
2017-02-12 13:55:49 +01:00
if ( stencilUploadPS_ )
2017-02-08 18:07:34 +01:00
stencilUploadPS_ - > Release ( ) ;
2017-02-12 13:55:49 +01:00
if ( stencilUploadVS_ )
2017-02-08 18:07:34 +01:00
stencilUploadVS_ - > Release ( ) ;
2017-02-12 13:55:49 +01:00
if ( stencilUploadInputLayout_ )
stencilUploadInputLayout_ - > Release ( ) ;
2017-02-13 17:29:36 +01:00
if ( stencilValueBuffer_ )
stencilValueBuffer_ - > Release ( ) ;
2018-08-30 21:00:21 -07:00
if ( nullTextureView_ )
nullTextureView_ - > Release ( ) ;
if ( nullTexture_ )
nullTexture_ - > Release ( ) ;
2017-02-08 18:07:34 +01:00
}
void FramebufferManagerD3D11 : : SetTextureCache ( TextureCacheD3D11 * tc ) {
textureCacheD3D11_ = tc ;
textureCache_ = tc ;
}
2017-02-15 18:32:44 +01:00
void FramebufferManagerD3D11 : : SetShaderManager ( ShaderManagerD3D11 * sm ) {
shaderManagerD3D11_ = sm ;
shaderManager_ = sm ;
}
2017-10-18 12:26:02 +02:00
void FramebufferManagerD3D11 : : SetDrawEngine ( DrawEngineD3D11 * td ) {
drawEngineD3D11_ = td ;
drawEngine_ = td ;
}
2017-05-31 23:24:56 -07:00
void FramebufferManagerD3D11 : : DrawActiveTexture ( float x , float y , float w , float h , float destW , float destH , float u0 , float v0 , float u1 , float v1 , int uvRotation , int flags ) {
2017-03-07 13:00:59 +01:00
struct Coord {
2019-10-22 22:58:10 +02:00
Lin : : Vec3 pos ; float u , v ;
2017-03-07 13:00:59 +01:00
} ;
Coord coord [ 4 ] = {
{ { x , y , 0 } , u0 , v0 } ,
{ { x + w , y , 0 } , u1 , v0 } ,
{ { x + w , y + h , 0 } , u1 , v1 } ,
{ { x , y + h , 0 } , u0 , v1 } ,
2017-02-08 18:07:34 +01:00
} ;
static const short indices [ 4 ] = { 0 , 1 , 3 , 2 } ;
if ( uvRotation ! = ROTATION_LOCKED_HORIZONTAL ) {
float temp [ 8 ] ;
int rotation = 0 ;
switch ( uvRotation ) {
case ROTATION_LOCKED_HORIZONTAL180 : rotation = 2 ; break ;
case ROTATION_LOCKED_VERTICAL : rotation = 1 ; break ;
case ROTATION_LOCKED_VERTICAL180 : rotation = 3 ; break ;
}
for ( int i = 0 ; i < 4 ; i + + ) {
2017-03-07 13:00:59 +01:00
temp [ i * 2 ] = coord [ ( ( i + rotation ) & 3 ) ] . u ;
temp [ i * 2 + 1 ] = coord [ ( ( i + rotation ) & 3 ) ] . v ;
2017-02-08 18:07:34 +01:00
}
for ( int i = 0 ; i < 4 ; i + + ) {
2017-03-07 13:00:59 +01:00
coord [ i ] . u = temp [ i * 2 ] ;
coord [ i ] . v = temp [ i * 2 + 1 ] ;
2017-02-08 18:07:34 +01:00
}
}
float invDestW = 1.0f / ( destW * 0.5f ) ;
float invDestH = 1.0f / ( destH * 0.5f ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
2017-03-19 14:57:48 +01:00
coord [ i ] . pos . x = coord [ i ] . pos . x * invDestW - 1.0f ;
coord [ i ] . pos . y = - ( coord [ i ] . pos . y * invDestH - 1.0f ) ;
2017-03-07 13:00:59 +01:00
}
if ( g_display_rotation ! = DisplayRotation : : ROTATE_0 ) {
for ( int i = 0 ; i < 4 ; i + + ) {
// backwards notation, should fix that...
coord [ i ] . pos = coord [ i ] . pos * g_display_rot_matrix ;
}
2017-02-08 18:07:34 +01:00
}
2017-02-12 11:20:55 +01:00
// The above code is for FAN geometry but we can only do STRIP. So rearrange it a little.
D3D11_MAPPED_SUBRESOURCE map ;
context_ - > Map ( quadBuffer_ , 0 , D3D11_MAP_WRITE_DISCARD , 0 , & map ) ;
float * dest = ( float * ) map . pData ;
2017-03-07 13:00:59 +01:00
memcpy ( dest , coord , sizeof ( Coord ) ) ;
memcpy ( dest + 5 , coord + 1 , sizeof ( Coord ) ) ;
memcpy ( dest + 10 , coord + 3 , sizeof ( Coord ) ) ;
memcpy ( dest + 15 , coord + 2 , sizeof ( Coord ) ) ;
2017-02-12 11:20:55 +01:00
context_ - > Unmap ( quadBuffer_ , 0 ) ;
2017-02-08 18:07:34 +01:00
context_ - > RSSetState ( stockD3D11 . rasterStateNoCull ) ;
context_ - > OMSetBlendState ( stockD3D11 . blendStateDisabledWithColorMask [ 0xF ] , nullptr , 0xFFFFFFFF ) ;
2017-02-12 11:20:55 +01:00
context_ - > OMSetDepthStencilState ( stockD3D11 . depthStencilDisabled , 0 ) ;
2017-02-08 18:07:34 +01:00
context_ - > IASetPrimitiveTopology ( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ) ;
2017-05-31 23:24:56 -07:00
context_ - > PSSetSamplers ( 0 , 1 , ( flags & DRAWTEX_LINEAR ) ? & stockD3D11 . samplerLinear2DClamp : & stockD3D11 . samplerPoint2DClamp ) ;
2017-02-12 11:20:55 +01:00
UINT stride = 20 ;
UINT offset = 0 ;
context_ - > IASetVertexBuffers ( 0 , 1 , & quadBuffer_ , & stride , & offset ) ;
context_ - > Draw ( 4 , 0 ) ;
2017-01-30 12:07:26 +01:00
gstate_c . Dirty ( DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE ) ;
2017-02-15 16:01:59 +01:00
}
void FramebufferManagerD3D11 : : Bind2DShader ( ) {
context_ - > IASetInputLayout ( quadInputLayout_ ) ;
context_ - > PSSetShader ( quadPixelShader_ , 0 , 0 ) ;
context_ - > VSSetShader ( quadVertexShader_ , 0 , 0 ) ;
}
2017-02-08 18:07:34 +01:00
void FramebufferManagerD3D11 : : ReformatFramebufferFrom ( VirtualFramebuffer * vfb , GEBufferFormat old ) {
if ( ! useBufferedRendering_ | | ! vfb - > fbo ) {
return ;
}
// Technically, we should at this point re-interpret the bytes of the old format to the new.
// That might get tricky, and could cause unnecessary slowness in some games.
// For now, we just clear alpha/stencil from 565, which fixes shadow issues in Kingdom Hearts.
2018-08-30 21:00:21 -07:00
// (it uses 565 to write zeros to the buffer, then 4444 to actually render the shadow.)
2017-02-08 18:07:34 +01:00
//
// The best way to do this may ultimately be to create a new FBO (combine with any resize?)
// and blit with a shader to that, then replace the FBO on vfb. Stencil would still be complex
// to exactly reproduce in 4444 and 8888 formats.
if ( old = = GE_FORMAT_565 ) {
2018-08-30 21:00:21 -07:00
draw_ - > BindFramebufferAsRenderTarget ( vfb - > fbo , { Draw : : RPAction : : KEEP , Draw : : RPAction : : KEEP , Draw : : RPAction : : CLEAR } ) ;
2017-05-23 11:12:10 +02:00
2018-08-30 21:00:21 -07:00
context_ - > OMSetDepthStencilState ( stockD3D11 . depthStencilDisabled , 0xFF ) ;
context_ - > OMSetBlendState ( stockD3D11 . blendStateDisabledWithColorMask [ D3D11_COLOR_WRITE_ENABLE_ALPHA ] , nullptr , 0xFFFFFFFF ) ;
2017-02-08 18:07:34 +01:00
context_ - > RSSetState ( stockD3D11 . rasterStateNoCull ) ;
2017-02-12 13:55:49 +01:00
context_ - > IASetInputLayout ( quadInputLayout_ ) ;
2017-02-12 11:20:55 +01:00
context_ - > PSSetShader ( quadPixelShader_ , nullptr , 0 ) ;
context_ - > VSSetShader ( quadVertexShader_ , nullptr , 0 ) ;
2017-02-12 13:55:49 +01:00
context_ - > IASetVertexBuffers ( 0 , 1 , & fsQuadBuffer_ , & quadStride_ , & quadOffset_ ) ;
2018-08-30 21:00:21 -07:00
context_ - > PSSetSamplers ( 0 , 1 , & stockD3D11 . samplerPoint2DClamp ) ;
context_ - > PSSetShaderResources ( 0 , 1 , & nullTextureView_ ) ;
2017-02-15 18:32:44 +01:00
shaderManagerD3D11_ - > DirtyLastShader ( ) ;
2017-02-08 18:07:34 +01:00
D3D11_VIEWPORT vp { 0.0f , 0.0f , ( float ) vfb - > renderWidth , ( float ) vfb - > renderHeight , 0.0f , 1.0f } ;
context_ - > RSSetViewports ( 1 , & vp ) ;
context_ - > IASetPrimitiveTopology ( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ) ;
2017-02-17 17:00:35 +01:00
context_ - > Draw ( 4 , 0 ) ;
2017-02-08 18:07:34 +01:00
2018-08-30 21:00:21 -07:00
textureCache_ - > ForgetLastTexture ( ) ;
gstate_c . Dirty ( DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE ) ;
}
2017-02-08 18:07:34 +01:00
}
static void CopyPixelDepthOnly ( u32 * dstp , const u32 * srcp , size_t c ) {
size_t x = 0 ;
# ifdef _M_SSE
size_t sseSize = ( c / 4 ) * 4 ;
const __m128i srcMask = _mm_set1_epi32 ( 0x00FFFFFF ) ;
const __m128i dstMask = _mm_set1_epi32 ( 0xFF000000 ) ;
__m128i * dst = ( __m128i * ) dstp ;
const __m128i * src = ( const __m128i * ) srcp ;
for ( ; x < sseSize ; x + = 4 ) {
const __m128i bits24 = _mm_and_si128 ( _mm_load_si128 ( src ) , srcMask ) ;
const __m128i bits8 = _mm_and_si128 ( _mm_load_si128 ( dst ) , dstMask ) ;
_mm_store_si128 ( dst , _mm_or_si128 ( bits24 , bits8 ) ) ;
dst + + ;
src + + ;
}
# endif
// Copy the remaining pixels that didn't fit in SSE.
for ( ; x < c ; + + x ) {
memcpy ( dstp + x , srcp + x , 3 ) ;
}
}
void FramebufferManagerD3D11 : : BlitFramebufferDepth ( VirtualFramebuffer * src , VirtualFramebuffer * dst ) {
bool matchingDepthBuffer = src - > z_address = = dst - > z_address & & src - > z_stride ! = 0 & & dst - > z_stride ! = 0 ;
bool matchingSize = src - > width = = dst - > width & & src - > height = = dst - > height ;
2017-02-17 12:51:37 +01:00
bool matchingRenderSize = src - > renderWidth = = dst - > renderWidth & & src - > renderHeight = = dst - > renderHeight ;
if ( matchingDepthBuffer & & matchingSize & & matchingRenderSize ) {
2017-06-01 20:57:08 -07:00
// TODO: Currently, this copies depth AND stencil, which is a problem. See #9740.
2017-02-13 01:22:55 +01:00
draw_ - > CopyFramebufferImage ( src - > fbo , 0 , 0 , 0 , 0 , dst - > fbo , 0 , 0 , 0 , 0 , src - > renderWidth , src - > renderHeight , 1 , Draw : : FB_DEPTH_BIT ) ;
2017-02-08 18:07:34 +01:00
RebindFramebuffer ( ) ;
2017-12-24 11:52:15 -08:00
dst - > last_frame_depth_updated = gpuStats . numFlips ;
2017-02-12 11:20:55 +01:00
}
2017-02-08 18:07:34 +01:00
}
2017-02-17 14:30:42 +01:00
void FramebufferManagerD3D11 : : BindFramebufferAsColorTexture ( int stage , VirtualFramebuffer * framebuffer , int flags ) {
2017-02-08 18:07:34 +01:00
if ( ! framebuffer - > fbo | | ! useBufferedRendering_ ) {
2017-02-10 11:25:24 +01:00
ID3D11ShaderResourceView * view = nullptr ;
context_ - > PSSetShaderResources ( stage , 1 , & view ) ;
2017-02-08 18:07:34 +01:00
gstate_c . skipDrawReason | = SKIPDRAW_BAD_FB_TEXTURE ;
return ;
}
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
// Let's just not bother with the copy in that case.
bool skipCopy = ( flags & BINDFBCOLOR_MAY_COPY ) = = 0 ;
2019-02-08 15:02:31 +01:00
if ( GPUStepping : : IsStepping ( ) ) {
2017-02-08 18:07:34 +01:00
skipCopy = true ;
}
// Currently rendering to this framebuffer. Need to make a copy.
2017-02-17 14:30:42 +01:00
if ( ! skipCopy & & framebuffer = = currentRenderVfb_ ) {
2017-02-08 18:07:34 +01:00
// TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size.
2018-05-06 08:57:44 -07:00
Draw : : Framebuffer * renderCopy = GetTempFBO ( TempFBO : : COPY , framebuffer - > renderWidth , framebuffer - > renderHeight , ( Draw : : FBColorDepth ) framebuffer - > colorDepth ) ;
2017-02-08 18:07:34 +01:00
if ( renderCopy ) {
VirtualFramebuffer copyInfo = * framebuffer ;
copyInfo . fbo = renderCopy ;
2017-04-06 18:49:48 -07:00
CopyFramebufferForColorTexture ( & copyInfo , framebuffer , flags ) ;
2017-02-08 18:07:34 +01:00
RebindFramebuffer ( ) ;
draw_ - > BindFramebufferAsTexture ( renderCopy , stage , Draw : : FB_COLOR_BIT , 0 ) ;
} else {
draw_ - > BindFramebufferAsTexture ( framebuffer - > fbo , stage , Draw : : FB_COLOR_BIT , 0 ) ;
}
2018-11-24 10:19:10 -08:00
} else if ( framebuffer ! = currentRenderVfb_ | | ( flags & BINDFBCOLOR_FORCE_SELF ) ! = 0 ) {
2017-02-08 18:07:34 +01:00
draw_ - > BindFramebufferAsTexture ( framebuffer - > fbo , stage , Draw : : FB_COLOR_BIT , 0 ) ;
2017-02-17 14:30:42 +01:00
} else {
2017-11-30 15:40:55 -08:00
ERROR_LOG_REPORT_ONCE ( d3d11SelfTexture , G3D , " Attempting to texture from target (src=%08x / target=%08x / flags=%d) " , framebuffer - > fb_address , currentRenderVfb_ - > fb_address , flags ) ;
2017-02-17 14:30:42 +01:00
// Badness on D3D11 to bind the currently rendered-to framebuffer as a texture.
ID3D11ShaderResourceView * view = nullptr ;
context_ - > PSSetShaderResources ( stage , 1 , & view ) ;
gstate_c . skipDrawReason | = SKIPDRAW_BAD_FB_TEXTURE ;
return ;
2017-02-08 18:07:34 +01:00
}
}
bool FramebufferManagerD3D11 : : CreateDownloadTempBuffer ( VirtualFramebuffer * nvfb ) {
nvfb - > colorDepth = Draw : : FBO_8888 ;
2018-06-01 21:16:07 +02:00
nvfb - > fbo = draw_ - > CreateFramebuffer ( { nvfb - > bufferWidth , nvfb - > bufferHeight , 1 , 1 , true , ( Draw : : FBColorDepth ) nvfb - > colorDepth } ) ;
2017-02-08 18:07:34 +01:00
if ( ! ( nvfb - > fbo ) ) {
2017-03-13 12:32:21 +01:00
ERROR_LOG ( FRAMEBUF , " Error creating FBO! %i x %i " , nvfb - > renderWidth , nvfb - > renderHeight ) ;
2017-02-08 18:07:34 +01:00
return false ;
}
2017-12-30 22:52:22 +01:00
draw_ - > BindFramebufferAsRenderTarget ( nvfb - > fbo , { Draw : : RPAction : : CLEAR , Draw : : RPAction : : CLEAR , Draw : : RPAction : : CLEAR } ) ;
2017-02-08 18:07:34 +01:00
return true ;
}
void FramebufferManagerD3D11 : : UpdateDownloadTempBuffer ( VirtualFramebuffer * nvfb ) {
// Nothing to do here.
}
2017-02-17 12:51:37 +01:00
void FramebufferManagerD3D11 : : SimpleBlit (
Draw : : Framebuffer * dest , float destX1 , float destY1 , float destX2 , float destY2 ,
Draw : : Framebuffer * src , float srcX1 , float srcY1 , float srcX2 , float srcY2 , bool linearFilter ) {
int destW , destH , srcW , srcH ;
draw_ - > GetFramebufferDimensions ( src , & srcW , & srcH ) ;
draw_ - > GetFramebufferDimensions ( dest , & destW , & destH ) ;
if ( srcW = = destW & & srcH = = destH & & destX2 - destX1 = = srcX2 - srcX1 & & destY2 - destY1 = = srcY2 - srcY1 ) {
// Optimize to a copy
draw_ - > CopyFramebufferImage ( src , 0 , ( int ) srcX1 , ( int ) srcY1 , 0 , dest , 0 , ( int ) destX1 , ( int ) destY1 , 0 , ( int ) ( srcX2 - srcX1 ) , ( int ) ( srcY2 - srcY1 ) , 1 , Draw : : FB_COLOR_BIT ) ;
return ;
}
float dX = 1.0f / ( float ) destW ;
float dY = 1.0f / ( float ) destH ;
float sX = 1.0f / ( float ) srcW ;
float sY = 1.0f / ( float ) srcH ;
struct Vtx {
float x , y , z , u , v ;
} ;
Vtx vtx [ 4 ] = {
2017-02-17 18:43:27 +01:00
{ - 1.0f + 2.0f * dX * destX1 , 1.0f - 2.0f * dY * destY1 , 0.0f , sX * srcX1 , sY * srcY1 } ,
{ - 1.0f + 2.0f * dX * destX2 , 1.0f - 2.0f * dY * destY1 , 0.0f , sX * srcX2 , sY * srcY1 } ,
{ - 1.0f + 2.0f * dX * destX1 , 1.0f - 2.0f * dY * destY2 , 0.0f , sX * srcX1 , sY * srcY2 } ,
{ - 1.0f + 2.0f * dX * destX2 , 1.0f - 2.0f * dY * destY2 , 0.0f , sX * srcX2 , sY * srcY2 } ,
2017-02-17 12:51:37 +01:00
} ;
D3D11_MAPPED_SUBRESOURCE map ;
2017-03-05 13:59:16 +01:00
ASSERT_SUCCESS ( context_ - > Map ( quadBuffer_ , 0 , D3D11_MAP_WRITE_DISCARD , 0 , & map ) ) ;
2017-02-17 12:51:37 +01:00
memcpy ( map . pData , vtx , 4 * sizeof ( Vtx ) ) ;
context_ - > Unmap ( quadBuffer_ , 0 ) ;
2017-03-19 17:53:26 +01:00
// Unbind the texture first to avoid the D3D11 hazard check (can't set render target to things bound as textures and vice versa, not even temporarily).
draw_ - > BindTexture ( 0 , nullptr ) ;
2017-12-30 22:52:22 +01:00
draw_ - > BindFramebufferAsRenderTarget ( dest , { Draw : : RPAction : : KEEP , Draw : : RPAction : : KEEP , Draw : : RPAction : : KEEP } ) ;
2017-03-19 17:53:26 +01:00
draw_ - > BindFramebufferAsTexture ( src , 0 , Draw : : FB_COLOR_BIT , 0 ) ;
2017-03-06 16:39:23 +01:00
2017-02-17 12:51:37 +01:00
Bind2DShader ( ) ;
2017-02-17 19:22:41 +01:00
D3D11_VIEWPORT vp { 0.0f , 0.0f , ( float ) destW , ( float ) destH , 0.0f , 1.0f } ;
context_ - > RSSetViewports ( 1 , & vp ) ;
2017-02-17 12:51:37 +01:00
context_ - > RSSetState ( stockD3D11 . rasterStateNoCull ) ;
context_ - > OMSetBlendState ( stockD3D11 . blendStateDisabledWithColorMask [ 0xF ] , nullptr , 0xFFFFFFFF ) ;
context_ - > OMSetDepthStencilState ( stockD3D11 . depthStencilDisabled , 0 ) ;
context_ - > IASetPrimitiveTopology ( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ) ;
context_ - > PSSetSamplers ( 0 , 1 , linearFilter ? & stockD3D11 . samplerLinear2DClamp : & stockD3D11 . samplerPoint2DClamp ) ;
UINT stride = sizeof ( Vtx ) ;
UINT offset = 0 ;
context_ - > IASetVertexBuffers ( 0 , 1 , & quadBuffer_ , & stride , & offset ) ;
context_ - > Draw ( 4 , 0 ) ;
2017-01-30 11:56:14 +01:00
2017-01-30 14:04:20 +01:00
gstate_c . Dirty ( DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_VERTEXSHADER_STATE ) ;
2017-02-17 12:51:37 +01:00
}
2017-02-08 18:07:34 +01:00
void FramebufferManagerD3D11 : : BlitFramebuffer ( VirtualFramebuffer * dst , int dstX , int dstY , VirtualFramebuffer * src , int srcX , int srcY , int w , int h , int bpp ) {
if ( ! dst - > fbo | | ! src - > fbo | | ! useBufferedRendering_ ) {
// This can happen if they recently switched from non-buffered.
2017-05-16 16:00:34 +02:00
if ( useBufferedRendering_ ) {
2017-12-30 22:52:22 +01:00
draw_ - > BindFramebufferAsRenderTarget ( nullptr , { Draw : : RPAction : : KEEP , Draw : : RPAction : : KEEP , Draw : : RPAction : : KEEP } ) ;
2017-05-16 16:00:34 +02:00
}
2017-02-08 18:07:34 +01:00
return ;
}
float srcXFactor = ( float ) src - > renderWidth / ( float ) src - > bufferWidth ;
float srcYFactor = ( float ) src - > renderHeight / ( float ) src - > bufferHeight ;
const int srcBpp = src - > format = = GE_FORMAT_8888 ? 4 : 2 ;
if ( srcBpp ! = bpp & & bpp ! = 0 ) {
srcXFactor = ( srcXFactor * bpp ) / srcBpp ;
}
int srcX1 = srcX * srcXFactor ;
int srcX2 = ( srcX + w ) * srcXFactor ;
int srcY1 = srcY * srcYFactor ;
int srcY2 = ( srcY + h ) * srcYFactor ;
float dstXFactor = ( float ) dst - > renderWidth / ( float ) dst - > bufferWidth ;
float dstYFactor = ( float ) dst - > renderHeight / ( float ) dst - > bufferHeight ;
const int dstBpp = dst - > format = = GE_FORMAT_8888 ? 4 : 2 ;
if ( dstBpp ! = bpp & & bpp ! = 0 ) {
dstXFactor = ( dstXFactor * bpp ) / dstBpp ;
}
int dstX1 = dstX * dstXFactor ;
int dstX2 = ( dstX + w ) * dstXFactor ;
int dstY1 = dstY * dstYFactor ;
int dstY2 = ( dstY + h ) * dstYFactor ;
2017-02-17 18:43:27 +01:00
// Direct3D doesn't support rect -> self.
2017-02-08 18:07:34 +01:00
Draw : : Framebuffer * srcFBO = src - > fbo ;
if ( src = = dst ) {
2018-05-06 08:57:44 -07:00
Draw : : Framebuffer * tempFBO = GetTempFBO ( TempFBO : : BLIT , src - > renderWidth , src - > renderHeight , ( Draw : : FBColorDepth ) src - > colorDepth ) ;
2017-02-17 12:51:37 +01:00
SimpleBlit ( tempFBO , dstX1 , dstY1 , dstX2 , dstY2 , src - > fbo , srcX1 , srcY1 , srcX2 , srcY2 , false ) ;
srcFBO = tempFBO ;
2017-02-08 18:07:34 +01:00
}
2017-02-17 12:51:37 +01:00
SimpleBlit (
2017-02-08 18:07:34 +01:00
dst - > fbo , dstX1 , dstY1 , dstX2 , dstY2 ,
2017-02-17 12:51:37 +01:00
srcFBO , srcX1 , srcY1 , srcX2 , srcY2 ,
false ) ;
2017-02-08 18:07:34 +01:00
}
2017-02-14 12:42:35 +01:00
// Nobody calls this yet.
2017-02-08 18:07:34 +01:00
void FramebufferManagerD3D11 : : PackDepthbuffer ( VirtualFramebuffer * vfb , int x , int y , int w , int h ) {
if ( ! vfb - > fbo ) {
ERROR_LOG_REPORT_ONCE ( vfbfbozero , SCEGE , " PackDepthbuffer: vfb->fbo == 0 " ) ;
return ;
}
2018-11-11 10:54:28 +01:00
const u32 z_address = vfb - > z_address ;
2017-02-14 12:42:35 +01:00
// TODO
2017-02-08 18:07:34 +01:00
}
void FramebufferManagerD3D11 : : EndFrame ( ) {
}
void FramebufferManagerD3D11 : : DeviceLost ( ) {
2017-04-13 23:07:21 -07:00
DestroyAllFBOs ( ) ;
2017-02-08 18:07:34 +01:00
}