diff --git a/GPU/D3D11/D3D11Util.cpp b/GPU/D3D11/D3D11Util.cpp index 10766491c9..baff704f05 100644 --- a/GPU/D3D11/D3D11Util.cpp +++ b/GPU/D3D11/D3D11Util.cpp @@ -57,6 +57,7 @@ void StockObjectsD3D11::Create(ID3D11Device *device) { blend_desc.RenderTarget[0].RenderTargetWriteMask = i; device->CreateBlendState(&blend_desc, &blendStateDisabledWithColorMask[i]); } + D3D11_DEPTH_STENCIL_DESC depth_desc{}; depth_desc.DepthEnable = FALSE; device->CreateDepthStencilState(&depth_desc, &depthStencilDisabled); @@ -72,11 +73,13 @@ void StockObjectsD3D11::Create(ID3D11Device *device) { depth_desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; depth_desc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; device->CreateDepthStencilState(&depth_desc, &depthDisabledStencilWrite); + D3D11_RASTERIZER_DESC raster_desc{}; raster_desc.FillMode = D3D11_FILL_SOLID; raster_desc.CullMode = D3D11_CULL_NONE; raster_desc.ScissorEnable = FALSE; device->CreateRasterizerState(&raster_desc, &rasterStateNoCull); + D3D11_SAMPLER_DESC sampler_desc{}; sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP; sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP; @@ -85,6 +88,13 @@ void StockObjectsD3D11::Create(ID3D11Device *device) { device->CreateSamplerState(&sampler_desc, &samplerPoint2DWrap); sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; device->CreateSamplerState(&sampler_desc, &samplerLinear2DWrap); + sampler_desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + sampler_desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + sampler_desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + device->CreateSamplerState(&sampler_desc, &samplerPoint2DClamp); + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + device->CreateSamplerState(&sampler_desc, &samplerLinear2DClamp); } void StockObjectsD3D11::Destroy() { diff --git a/GPU/D3D11/D3D11Util.h b/GPU/D3D11/D3D11Util.h index cbac7a972a..4718756731 100644 --- a/GPU/D3D11/D3D11Util.h +++ b/GPU/D3D11/D3D11Util.h @@ -78,6 +78,8 @@ public: ID3D11RasterizerState *rasterStateNoCull; ID3D11SamplerState *samplerPoint2DWrap; ID3D11SamplerState *samplerLinear2DWrap; + ID3D11SamplerState *samplerPoint2DClamp; + ID3D11SamplerState *samplerLinear2DClamp; }; extern StockObjectsD3D11 stockD3D11; \ No newline at end of file diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index d48bde41e1..4b47dfa89e 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -17,6 +17,7 @@ #include "math/lin/matrix4x4.h" #include "ext/native/thin3d/thin3d.h" +#include "base/basictypes.h" #include "Common/ColorConv.h" #include "Core/Host.h" @@ -43,7 +44,7 @@ #include #endif -static const char * vscode = +static const char *vscode = "struct VS_IN {\n" " float4 ObjPos : POSITION;\n" " float2 Uv : TEXCOORD0;\n" @@ -59,10 +60,7 @@ static const char * vscode = " return Out;\n" "}\n"; -//-------------------------------------------------------------------------------------- -// Pixel shader -//-------------------------------------------------------------------------------------- -static const char * pscode = +static const char *pscode = "SamplerState samp : register(s0);\n" "Texture2D tex : register(t0);\n" "struct PS_IN {\n" @@ -73,21 +71,11 @@ static const char * pscode = " return c;\n" "}\n"; -static const D3D11_INPUT_ELEMENT_DESC g_FramebufferVertexElements[] = { +static const D3D11_INPUT_ELEMENT_DESC g_QuadVertexElements[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, }, }; -void FramebufferManagerD3D11::ClearBuffer(bool keepState) { - draw_->Clear(Draw::ClearFlag::COLOR | Draw::ClearFlag::DEPTH | Draw::ClearFlag::STENCIL, 0, ToScaledDepth(0), 0); -} - -void FramebufferManagerD3D11::DisableState() { - context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], nullptr, 0xFFFFFFFF); - context_->RSSetState(stockD3D11.rasterStateNoCull); - context_->OMSetDepthStencilState(stockD3D11.depthStencilDisabled, 0xFF); -} - FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) : FramebufferManagerCommon(draw), drawPixelsTex_(0), @@ -102,20 +90,27 @@ FramebufferManagerD3D11::FramebufferManagerD3D11(Draw::DrawContext *draw) std::vector bytecode; std::string errorMsg; - pFramebufferVertexShader_ = CreateVertexShaderD3D11(device_, vscode, strlen(vscode), &bytecode); - pFramebufferPixelShader_ = CreatePixelShaderD3D11(device_, pscode, strlen(pscode)); - device_->CreateInputLayout(g_FramebufferVertexElements, ARRAY_SIZE(g_FramebufferVertexElements), bytecode.data(), bytecode.size(), &pFramebufferVertexDecl_); + quadVertexShader_ = CreateVertexShaderD3D11(device_, vscode, strlen(vscode), &bytecode); + quadPixelShader_ = CreatePixelShaderD3D11(device_, pscode, strlen(pscode)); + device_->CreateInputLayout(g_QuadVertexElements, ARRAY_SIZE(g_QuadVertexElements), bytecode.data(), bytecode.size(), &quadVertexDecl_); - float coord[20] = { - -1.0f,-1.0f, 0, 0,0, - 1.0f,-1.0f, 0, 0,0, - 1.0f,1.0f, 0, 0,0, - -1.0f,1.0f, 0, 0,0, + // 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, }; D3D11_BUFFER_DESC vb{}; vb.ByteWidth = 20 * 4; vb.Usage = D3D11_USAGE_IMMUTABLE; vb.CPUAccessFlags = 0; + vb.BindFlags = D3D11_BIND_VERTEX_BUFFER; + D3D11_SUBRESOURCE_DATA data{ fsCoord }; + device_->CreateBuffer(&vb, &data, &fsQuadBuffer_); + vb.Usage = D3D11_USAGE_DYNAMIC; + vb.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + device_->CreateBuffer(&vb, nullptr, &quadBuffer_); } FramebufferManagerD3D11::~FramebufferManagerD3D11() { @@ -123,21 +118,23 @@ FramebufferManagerD3D11::~FramebufferManagerD3D11() { if (vbFullScreenRect_) { vbFullScreenRect_->Release(); } - if (pFramebufferVertexShader_) { - pFramebufferVertexShader_->Release(); - pFramebufferVertexShader_ = nullptr; + if (quadVertexShader_) { + quadVertexShader_->Release(); + quadVertexShader_ = nullptr; } - if (pFramebufferPixelShader_) { - pFramebufferPixelShader_->Release(); - pFramebufferPixelShader_ = nullptr; + if (quadPixelShader_) { + quadPixelShader_->Release(); + quadPixelShader_ = nullptr; } - pFramebufferVertexDecl_->Release(); + quadVertexDecl_->Release(); if (drawPixelsTex_) { drawPixelsTex_->Release(); } if (drawPixelsTexView_) { drawPixelsTexView_->Release(); } + quadBuffer_->Release(); + fsQuadBuffer_->Release(); // FBO cleanup for (auto it = tempFBOs_.begin(), end = tempFBOs_.end(); it != end; ++it) { @@ -163,6 +160,16 @@ void FramebufferManagerD3D11::SetTextureCache(TextureCacheD3D11 *tc) { textureCache_ = tc; } +void FramebufferManagerD3D11::ClearBuffer(bool keepState) { + draw_->Clear(Draw::ClearFlag::COLOR | Draw::ClearFlag::DEPTH | Draw::ClearFlag::STENCIL, 0, ToScaledDepth(0), 0); +} + +void FramebufferManagerD3D11::DisableState() { + context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], nullptr, 0xFFFFFFFF); + context_->RSSetState(stockD3D11.rasterStateNoCull); + context_->OMSetDepthStencilState(stockD3D11.depthStencilDisabled, 0xFF); +} + void FramebufferManagerD3D11::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { u8 *convBuf = NULL; @@ -281,7 +288,6 @@ void FramebufferManagerD3D11::DrawFramebufferToOutput(const u8 *srcPixels, GEBuf } 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, bool linearFilter) { - // TODO: StretchRect instead? float coord[20] = { x,y,0, u0,v0, x + w,y,0, u1,v0, @@ -320,17 +326,30 @@ void FramebufferManagerD3D11::DrawActiveTexture(float x, float y, float w, float coord[i * 5 + 1] = -(coord[i * 5 + 1] * invDestH - 1.0f - halfPixelY); } + // 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; + memcpy(dest, coord, sizeof(float) * 5); + memcpy(dest + 5, coord + 5, sizeof(float) * 5); + memcpy(dest + 10, coord + 15, sizeof(float) * 5); + memcpy(dest + 15, coord + 10, sizeof(float) * 5); + context_->Unmap(quadBuffer_, 0); + context_->RSSetState(stockD3D11.rasterStateNoCull); context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], nullptr, 0xFFFFFFFF); - context_->IASetInputLayout(pFramebufferVertexDecl_); - context_->PSSetShader(pFramebufferPixelShader_, 0, 0); - context_->VSSetShader(pFramebufferVertexShader_, 0, 0); + context_->OMSetDepthStencilState(stockD3D11.depthStencilDisabled, 0); + context_->IASetInputLayout(quadVertexDecl_); + context_->PSSetShader(quadPixelShader_, 0, 0); + context_->VSSetShader(quadVertexShader_, 0, 0); context_->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - context_->PSSetSamplers(0, 1, linearFilter ? &stockD3D11.samplerLinear2DWrap : &stockD3D11.samplerPoint2DWrap); + context_->PSSetSamplers(0, 1, linearFilter ? &stockD3D11.samplerLinear2DClamp : &stockD3D11.samplerPoint2DClamp); + UINT stride = 20; + UINT offset = 0; + context_->IASetVertexBuffers(0, 1, &quadBuffer_, &stride, &offset); + context_->Draw(4, 0); - // TODO: DrawRectBuffer ? shaderManager_->DirtyLastShader(); - context_->Draw(2, 0); } void FramebufferManagerD3D11::RebindFramebuffer() { @@ -361,9 +380,9 @@ void FramebufferManagerD3D11::ReformatFramebufferFrom(VirtualFramebuffer *vfb, G context_->OMSetDepthStencilState(stockD3D11.depthDisabledStencilWrite, 0xFF); context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0], nullptr, 0xFFFFFFFF); context_->RSSetState(stockD3D11.rasterStateNoCull); - context_->IASetInputLayout(pFramebufferVertexDecl_); - context_->PSSetShader(pFramebufferPixelShader_, nullptr, 0); - context_->VSSetShader(pFramebufferVertexShader_, nullptr, 0); + context_->IASetInputLayout(quadVertexDecl_); + context_->PSSetShader(quadPixelShader_, nullptr, 0); + context_->VSSetShader(quadVertexShader_, nullptr, 0); context_->IASetVertexBuffers(0, 1, &vbFullScreenRect_, &vbFullScreenStride_, &vbFullScreenOffset_); shaderManager_->DirtyLastShader(); D3D11_VIEWPORT vp{ 0.0f, 0.0f, (float)vfb->renderWidth, (float)vfb->renderHeight, 0.0f, 1.0f }; @@ -404,13 +423,13 @@ void FramebufferManagerD3D11::BlitFramebufferDepth(VirtualFramebuffer *src, Virt if (g_Config.bDisableSlowFramebufEffects) { return; } - /* 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; if (matchingDepthBuffer && matchingSize) { // Doesn't work. Use a shader maybe? draw_->BindBackbufferAsRenderTarget(); - + draw_->CopyFramebufferImage(src->fbo, 0, 0, 0, 0, dst->fbo, 0, 0, 0, 0, src->width, src->height, 1, Draw::FB_DEPTH_BIT); + /* LPDIRECT3DTEXTURE9 srcTex = (LPDIRECT3DTEXTURE9)draw_->GetFramebufferAPITexture(src->fbo, Draw::FB_DEPTH_BIT, 0); LPDIRECT3DTEXTURE9 dstTex = (LPDIRECT3DTEXTURE9)draw_->GetFramebufferAPITexture(dst->fbo, Draw::FB_DEPTH_BIT, 0); @@ -448,9 +467,9 @@ void FramebufferManagerD3D11::BlitFramebufferDepth(VirtualFramebuffer *src, Virt dstTex->UnlockRect(0); } } - RebindFramebuffer(); - }*/ + */ + } } void FramebufferManagerD3D11::BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, int flags) { @@ -527,10 +546,11 @@ void FramebufferManagerD3D11::CopyDisplayToOutput() { if (useBufferedRendering_) { // In buffered, we no longer clear the backbuffer before we start rendering. ClearBuffer(); - D3D11_VIEWPORT vp{ 0.0f, 0.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, 0.0f, 1.0f }; - context_->RSSetViewports(1, &vp); } + D3D11_VIEWPORT vp{ 0.0f, 0.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, 0.0f, 1.0f }; + context_->RSSetViewports(1, &vp); + u32 offsetX = 0; u32 offsetY = 0; @@ -630,19 +650,9 @@ void FramebufferManagerD3D11::CopyDisplayToOutput() { if (1) { const u32 rw = PSP_CoreParameter().pixelWidth; const u32 rh = PSP_CoreParameter().pixelHeight; - bool result = draw_->BlitFramebuffer(vfb->fbo, - (LONG)(u0 * vfb->renderWidth), (LONG)(v0 * vfb->renderHeight), (LONG)(u1 * vfb->renderWidth), (LONG)(v1 * vfb->renderHeight), - nullptr, - (LONG)(x * rw / w), (LONG)(y * rh / h), (LONG)((x + w) * rw / w), (LONG)((y + h) * rh / h), - Draw::FB_COLOR_BIT, - g_Config.iBufFilter == SCALE_LINEAR ? Draw::FB_BLIT_LINEAR : Draw::FB_BLIT_NEAREST); - if (!result) { - ERROR_LOG_REPORT_ONCE(blit_fail, G3D, "fbo_blit_color failed on display"); - D3D11_VIEWPORT vp{ 0.0f, 0.0f, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, 0.0f, 1.0f }; - context_->RSSetViewports(1, &vp); - DrawActiveTexture(x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation, g_Config.iBufFilter == SCALE_LINEAR); - } + DrawActiveTexture(x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation, g_Config.iBufFilter == SCALE_LINEAR); } + /* else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) { // An additional pass, post-processing shader to the extra FBO. diff --git a/GPU/D3D11/FramebufferManagerD3D11.h b/GPU/D3D11/FramebufferManagerD3D11.h index 5527d54297..18c6ab359d 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.h +++ b/GPU/D3D11/FramebufferManagerD3D11.h @@ -110,9 +110,12 @@ private: int drawPixelsTexW_; int drawPixelsTexH_; - ID3D11VertexShader *pFramebufferVertexShader_; - ID3D11PixelShader *pFramebufferPixelShader_; - ID3D11InputLayout *pFramebufferVertexDecl_; + ID3D11VertexShader *quadVertexShader_; + ID3D11PixelShader *quadPixelShader_; + ID3D11InputLayout *quadVertexDecl_; + // Dynamic + ID3D11Buffer *quadBuffer_; + ID3D11Buffer *fsQuadBuffer_; u8 *convBuf; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index 978a292550..395e3eee80 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -509,6 +509,8 @@ void GPU_D3D11::CheckGPUFeatures() { features |= GPU_SUPPORTS_ANISOTROPY; features |= GPU_SUPPORTS_OES_TEXTURE_NPOT; + // features |= GPU_SUPPORTS_ANY_COPY_IMAGE; + if (!g_Config.bHighQualityDepth) { features |= GPU_SCALE_DEPTH_FROM_24BIT_TO_16BIT; } else if (PSP_CoreParameter().compat.flags().PixelDepthRounding) { diff --git a/GPU/D3D11/StateMappingD3D11.cpp b/GPU/D3D11/StateMappingD3D11.cpp index 02f9329dcf..ece0497732 100644 --- a/GPU/D3D11/StateMappingD3D11.cpp +++ b/GPU/D3D11/StateMappingD3D11.cpp @@ -198,12 +198,6 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { bool useBufferedRendering = g_Config.iRenderingMode != FB_NON_BUFFERED_MODE; - ViewportAndScissor vpAndScissor; - ConvertViewportAndScissor(useBufferedRendering, - framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), - framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), - vpAndScissor); - if (blendState.applyShaderBlending) { if (ApplyShaderBlending()) { // We may still want to do something about stencil -> alpha. @@ -357,22 +351,11 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { dynState.topology = primToD3D11[prim]; - D3D11_VIEWPORT &vp = dynState.viewport; - vp.TopLeftX = vpAndScissor.viewportX; - vp.TopLeftY = vpAndScissor.viewportY; - vp.Width = vpAndScissor.viewportW; - vp.Height = vpAndScissor.viewportH; - vp.MinDepth = vpAndScissor.depthRangeMin; - vp.MaxDepth = vpAndScissor.depthRangeMax; - if (vpAndScissor.dirtyProj) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } - - D3D11_RECT &scissor = dynState.scissor; - scissor.left = vpAndScissor.scissorX; - scissor.top = vpAndScissor.scissorY; - scissor.right = vpAndScissor.scissorX + vpAndScissor.scissorW; - scissor.bottom = vpAndScissor.scissorY + vpAndScissor.scissorH; + ViewportAndScissor vpAndScissor; + ConvertViewportAndScissor(useBufferedRendering, + framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(), + framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(), + vpAndScissor); float depthMin = vpAndScissor.depthRangeMin; float depthMax = vpAndScissor.depthRangeMax; @@ -383,6 +366,26 @@ void DrawEngineD3D11::ApplyDrawState(int prim) { gstate_c.Dirty(DIRTY_DEPTHRANGE); } + D3D11_VIEWPORT &vp = dynState.viewport; + vp.TopLeftX = vpAndScissor.viewportX; + vp.TopLeftY = vpAndScissor.viewportY; + vp.Width = vpAndScissor.viewportW; + vp.Height = vpAndScissor.viewportH; + vp.MinDepth = depthMin; + vp.MaxDepth = depthMax; + if (vpAndScissor.dirtyProj) { + gstate_c.Dirty(DIRTY_PROJMATRIX); + } + context_->RSSetViewports(1, &vp); + + /* + D3D11_RECT &scissor = dynState.scissor; + scissor.left = vpAndScissor.scissorX; + scissor.top = vpAndScissor.scissorY; + scissor.right = vpAndScissor.scissorX + vpAndScissor.scissorW; + scissor.bottom = vpAndScissor.scissorY + vpAndScissor.scissorH; + context_->RSSetScissorRects(0, &scissor); + */ if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) { textureCache_->SetTexture(); gstate_c.Clean(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS); diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index c418e31786..3fbe3479d7 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -57,7 +57,7 @@ #define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in VRAM #define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024 -static const D3D11_INPUT_ELEMENT_DESC g_FramebufferVertexElements[] = { +static const D3D11_INPUT_ELEMENT_DESC g_QuadVertexElements[] = { { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, }, { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12,}, }; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 04b568b6f5..a22737938b 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -1021,7 +1021,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, const bool xOverlap = src == dst && srcX2 > dstX1 && srcX1 < dstX2; const bool yOverlap = src == dst && srcY2 > dstY1 && srcY1 < dstY2; if (sameSize && sameDepth && srcInsideBounds && dstInsideBounds && !(xOverlap && yOverlap)) { - draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1); + draw_->CopyFramebufferImage(src->fbo, 0, srcX1, srcY1, 0, dst->fbo, 0, dstX1, dstY1, 0, dstX2 - dstX1, dstY2 - dstY1, 1, Draw::FB_COLOR_BIT); return; } } diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 2f3eec4aac..c88309eb9f 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -582,7 +582,7 @@ public: // Copies data from the CPU over into the buffer, at a specific offset. This does not change the size of the buffer and cannot write outside it. virtual void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) = 0; - virtual void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) = 0; + virtual void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) = 0; virtual bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) = 0; // These functions should be self explanatory. diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index 67c36080c2..3d7587dd81 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -45,7 +45,7 @@ public: void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) override; + void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) override; // These functions should be self explanatory. @@ -1117,18 +1117,41 @@ void D3D11DrawContext::Clear(int mask, uint32_t colorval, float depthVal, int st } } -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) { +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 channelBits) { D3D11Framebuffer *src = (D3D11Framebuffer *)srcfb; D3D11Framebuffer *dst = (D3D11Framebuffer *)dstfb; - // CopySubResource ? + ID3D11Texture2D *srcTex = nullptr; + ID3D11Texture2D *dstTex = nullptr; + switch (channelBits) { + case FB_COLOR_BIT: + srcTex = src->colorTex; + dstTex = dst->colorTex; + break; + case FB_DEPTH_BIT: + srcTex = src->depthStencilTex; + dstTex = dst->depthStencilTex; + break; + } + + // TODO: Check for level too! + if (width == src->width && width == dst->width && height == src->height && height == dst->height && x == 0 && y == 0 && z == 0 && dstX == 0 && dstY == 0 && dstZ == 0) { + // Don't need to specify region. This might be faster, too. + context_->CopyResource(dstTex, srcTex); + return; + } + + D3D11_BOX srcBox{ + x, y, z, x+width, y+height, z+depth + }; + context_->CopySubresourceRegion(dstTex, dstLevel, dstX, dstY, dstZ, srcTex, level, &srcBox); } bool D3D11DrawContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) { D3D11Framebuffer *src = (D3D11Framebuffer *)srcfb; D3D11Framebuffer *dst = (D3D11Framebuffer *)dstfb; - // Unfortunately D3D11 has no equivalent to this, gotta render a quad. + // Unfortunately D3D11 has no equivalent to this, gotta render a quad. Well, in some cases we can issue a copy instead. return true; } diff --git a/ext/native/thin3d/thin3d_d3d9.cpp b/ext/native/thin3d/thin3d_d3d9.cpp index 811e7d0a2a..7b75b759a0 100644 --- a/ext/native/thin3d/thin3d_d3d9.cpp +++ b/ext/native/thin3d/thin3d_d3d9.cpp @@ -478,7 +478,7 @@ public: void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) override {} + void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) override {} bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) override; // These functions should be self explanatory. diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index b3fba72245..30c2539f4a 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -469,7 +469,7 @@ public: void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) override; + void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) override; // These functions should be self explanatory. @@ -1506,29 +1506,41 @@ void OpenGLContext::BindFramebufferForRead(Framebuffer *fbo) { fbo_bind_fb_target(true, fb->handle); } -void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) { +void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int srcX, int srcY, int srcZ, Framebuffer *fbdst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) { OpenGLFramebuffer *src = (OpenGLFramebuffer *)fbsrc; OpenGLFramebuffer *dst = (OpenGLFramebuffer *)fbdst; + GLuint srcTex = 0; + GLuint dstTex = 0; + switch (channelBits) { + case FB_COLOR_BIT: + srcTex = src->color_texture; + dstTex = dst->color_texture; + break; + case FB_DEPTH_BIT: + srcTex = src->z_buffer ? src->z_buffer : src->z_stencil_buffer; + dstTex = dst->z_buffer ? dst->z_buffer : dst->z_stencil_buffer; + break; + } #if defined(USING_GLES2) #ifndef IOS glCopyImageSubDataOES( - src->color_texture, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, - dst->color_texture, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + srcTex, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + dstTex, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, width, height, depth); return; #endif #else if (gl_extensions.ARB_copy_image) { glCopyImageSubData( - src->color_texture, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, - dst->color_texture, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + srcTex, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + dstTex, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, width, height, depth); return; } else if (gl_extensions.NV_copy_image) { // Older, pre GL 4.x NVIDIA cards. glCopyImageSubDataNV( - src->color_texture, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, - dst->color_texture, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, + srcTex, GL_TEXTURE_2D, srcLevel, srcX, srcY, srcZ, + dstTex, GL_TEXTURE_2D, dstLevel, dstX, dstY, dstZ, width, height, depth); return; } diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index c57058cec8..16f34b814e 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -340,7 +340,7 @@ public: void UpdateBuffer(Buffer *buffer, const uint8_t *data, size_t offset, size_t size, UpdateBufferFlags flags) override; - void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) override; + void CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth, int channelBits) override; bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) override; // These functions should be self explanatory. @@ -1280,17 +1280,34 @@ Framebuffer *VKContext::CreateFramebuffer(const FramebufferDesc &desc) { return fb; } -void VKContext::CopyFramebufferImage(Framebuffer *src, int level, int x, int y, int z, Framebuffer *dst, int dstLevel, int dstX, int dstY, int dstZ, int width, int height, int depth) {} -bool VKContext::BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) { return true; } +void VKContext::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 channelBits) { + VKFramebuffer *src = (VKFramebuffer *)srcfb; + VKFramebuffer *dst = (VKFramebuffer *)dstfb; +} +bool VKContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dstfb, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) { + VKFramebuffer *src = (VKFramebuffer *)srcfb; + VKFramebuffer *dst = (VKFramebuffer *)dstfb; + return true; +} // These functions should be self explanatory. -void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) {} +void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { + VKFramebuffer *fb = (VKFramebuffer *)fbo; +} // color must be 0, for now. -void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) {} -void VKContext::BindFramebufferForRead(Framebuffer *fbo) {} +void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) { + VKFramebuffer *fb = (VKFramebuffer *)fbo; -void VKContext::BindBackbufferAsRenderTarget() {} -uintptr_t VKContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { return 0; } +} +void VKContext::BindFramebufferForRead(Framebuffer *fbo) { /* noop */ } + +void VKContext::BindBackbufferAsRenderTarget() { + +} + +uintptr_t VKContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { + return 0; +} void VKContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) { VKFramebuffer *fb = (VKFramebuffer *)fbo;