diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters
index 0d11399460..38d3896534 100644
--- a/Common/Common.vcxproj.filters
+++ b/Common/Common.vcxproj.filters
@@ -729,10 +729,10 @@
Render\Text
-
+
GPU
-
+
GPU
diff --git a/Common/GPU/D3D11/thin3d_d3d11.cpp b/Common/GPU/D3D11/thin3d_d3d11.cpp
index ed7de24771..21db0ab5cb 100644
--- a/Common/GPU/D3D11/thin3d_d3d11.cpp
+++ b/Common/GPU/D3D11/thin3d_d3d11.cpp
@@ -294,6 +294,8 @@ D3D11DrawContext::D3D11DrawContext(ID3D11Device *device, ID3D11DeviceContext *de
packDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
hr = device_->CreateTexture2D(&packDesc, nullptr, &packTexture_);
_assert_(SUCCEEDED(hr));
+
+ shaderLanguageDesc_.Init(HLSL_D3D11);
}
D3D11DrawContext::~D3D11DrawContext() {
@@ -1205,7 +1207,10 @@ uint32_t D3D11DrawContext::GetDataFormatSupport(DataFormat fmt) const {
// A D3D11Framebuffer is a D3D11Framebuffer plus all the textures it owns.
class D3D11Framebuffer : public Framebuffer {
public:
- D3D11Framebuffer() {}
+ D3D11Framebuffer(int width, int height) {
+ width_ = width;
+ height_ = height;
+ }
~D3D11Framebuffer() {
if (colorTex)
colorTex->Release();
@@ -1220,8 +1225,6 @@ public:
if (depthStencilRTView)
depthStencilRTView->Release();
}
- int width;
- int height;
ID3D11Texture2D *colorTex = nullptr;
ID3D11RenderTargetView *colorRTView = nullptr;
@@ -1236,9 +1239,7 @@ public:
Framebuffer *D3D11DrawContext::CreateFramebuffer(const FramebufferDesc &desc) {
HRESULT hr;
- D3D11Framebuffer *fb = new D3D11Framebuffer();
- fb->width = desc.width;
- fb->height = desc.height;
+ D3D11Framebuffer *fb = new D3D11Framebuffer(desc.width, desc.height);
if (desc.numColorAttachments) {
fb->colorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
D3D11_TEXTURE2D_DESC descColor{};
@@ -1396,7 +1397,7 @@ void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x
}
// 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) {
+ 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;
@@ -1415,11 +1416,11 @@ void D3D11DrawContext::CopyFramebufferImage(Framebuffer *srcfb, int level, int x
dstY -= y;
y = 0;
}
- if (x + width > src->width) {
- width = src->width - x;
+ if (x + width > src->Width()) {
+ width = src->Width() - x;
}
- if (y + height > src->height) {
- height = src->height - y;
+ if (y + height > src->Height()) {
+ height = src->Height() - y;
}
D3D11_BOX srcBox{ (UINT)x, (UINT)y, (UINT)z, (UINT)(x + width), (UINT)(y + height), (UINT)(z + depth) };
context_->CopySubresourceRegion(dstTex, dstLevel, dstX, dstY, dstZ, srcTex, level, &srcBox);
@@ -1441,11 +1442,11 @@ bool D3D11DrawContext::CopyFramebufferToMemorySync(Framebuffer *src, int channel
_assert_(fb->colorFormat == DXGI_FORMAT_R8G8B8A8_UNORM);
// TODO: Figure out where the badness really comes from.
- if (bx + bw > fb->width) {
- bw -= (bx + bw) - fb->width;
+ if (bx + bw > fb->Width()) {
+ bw -= (bx + bw) - fb->Width();
}
- if (by + bh > fb->height) {
- bh -= (by + bh) - fb->height;
+ if (by + bh > fb->Height()) {
+ bh -= (by + bh) - fb->Height();
}
}
@@ -1565,8 +1566,8 @@ void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Ren
context_->OMSetRenderTargets(1, &fb->colorRTView, fb->depthStencilRTView);
curRenderTargetView_ = fb->colorRTView;
curDepthStencilView_ = fb->depthStencilRTView;
- curRTWidth_ = fb->width;
- curRTHeight_ = fb->height;
+ curRTWidth_ = fb->Width();
+ curRTHeight_ = fb->Height();
}
} else {
if (curRenderTargetView_ == bbRenderTargetView_ && curDepthStencilView_ == bbDepthStencilView_) {
@@ -1634,8 +1635,8 @@ uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int chann
void D3D11DrawContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo;
if (fb) {
- *w = fb->width;
- *h = fb->height;
+ *w = fb->Width();
+ *h = fb->Height();
} else {
*w = bbWidth_;
*h = bbHeight_;
diff --git a/Common/GPU/D3D9/thin3d_d3d9.cpp b/Common/GPU/D3D9/thin3d_d3d9.cpp
index 4665f6933f..44a559ee50 100644
--- a/Common/GPU/D3D9/thin3d_d3d9.cpp
+++ b/Common/GPU/D3D9/thin3d_d3d9.cpp
@@ -670,6 +670,8 @@ D3D9Context::D3D9Context(IDirect3D9 *d3d, IDirect3D9Ex *d3dEx, int adapterId, ID
HRESULT fboINTZ = d3d->CheckDeviceFormat(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_A8R8G8B8, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, FOURCC_INTZ);
supportsINTZ = SUCCEEDED(displayINTZ) && SUCCEEDED(fboINTZ);
}
+
+ shaderLanguageDesc_.Init(HLSL_D3D9);
}
D3D9Context::~D3D9Context() {
@@ -1072,26 +1074,26 @@ bool D3D9ShaderModule::Compile(LPDIRECT3DDEVICE9 device, const uint8_t *data, si
class D3D9Framebuffer : public Framebuffer {
public:
+ D3D9Framebuffer(int width, int height) {
+ width_ = width;
+ height_ = height;
+ }
~D3D9Framebuffer();
- uint32_t id;
- LPDIRECT3DSURFACE9 surf;
- LPDIRECT3DSURFACE9 depthstencil;
- LPDIRECT3DTEXTURE9 tex;
- LPDIRECT3DTEXTURE9 depthstenciltex;
- int width;
- int height;
+ uint32_t id = 0;
+ LPDIRECT3DSURFACE9 surf = nullptr;
+ LPDIRECT3DSURFACE9 depthstencil = nullptr;
+ LPDIRECT3DTEXTURE9 tex = nullptr;
+ LPDIRECT3DTEXTURE9 depthstenciltex = nullptr;
};
Framebuffer *D3D9Context::CreateFramebuffer(const FramebufferDesc &desc) {
static uint32_t id = 0;
- D3D9Framebuffer *fbo = new D3D9Framebuffer{};
- fbo->width = desc.width;
- fbo->height = desc.height;
+ D3D9Framebuffer *fbo = new D3D9Framebuffer(desc.width, desc.height);
fbo->depthstenciltex = nullptr;
- HRESULT rtResult = device_->CreateTexture(fbo->width, fbo->height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &fbo->tex, NULL);
+ HRESULT rtResult = device_->CreateTexture(desc.width, desc.height, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &fbo->tex, NULL);
if (FAILED(rtResult)) {
ERROR_LOG(G3D, "Failed to create render target");
delete fbo;
@@ -1101,12 +1103,12 @@ Framebuffer *D3D9Context::CreateFramebuffer(const FramebufferDesc &desc) {
HRESULT dsResult;
if (supportsINTZ) {
- dsResult = device_->CreateTexture(fbo->width, fbo->height, 1, D3DUSAGE_DEPTHSTENCIL, FOURCC_INTZ, D3DPOOL_DEFAULT, &fbo->depthstenciltex, NULL);
+ dsResult = device_->CreateTexture(desc.width, desc.height, 1, D3DUSAGE_DEPTHSTENCIL, FOURCC_INTZ, D3DPOOL_DEFAULT, &fbo->depthstenciltex, NULL);
if (SUCCEEDED(dsResult)) {
dsResult = fbo->depthstenciltex->GetSurfaceLevel(0, &fbo->depthstencil);
}
} else {
- dsResult = device_->CreateDepthStencilSurface(fbo->width, fbo->height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, &fbo->depthstencil, NULL);
+ dsResult = device_->CreateDepthStencilSurface(desc.width, desc.height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0, FALSE, &fbo->depthstencil, NULL);
}
if (FAILED(dsResult)) {
ERROR_LOG(G3D, "Failed to create depth buffer");
@@ -1208,8 +1210,8 @@ void D3D9Context::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChan
void D3D9Context::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo;
if (fb) {
- *w = fb->width;
- *h = fb->height;
+ *w = fb->Width();
+ *h = fb->Height();
} else {
*w = targetWidth_;
*h = targetHeight_;
diff --git a/Common/GPU/OpenGL/thin3d_gl.cpp b/Common/GPU/OpenGL/thin3d_gl.cpp
index 2dc7768029..ff5d0e08cf 100644
--- a/Common/GPU/OpenGL/thin3d_gl.cpp
+++ b/Common/GPU/OpenGL/thin3d_gl.cpp
@@ -350,6 +350,7 @@ public:
return (uint32_t)ShaderLanguage::GLSL_1xx;
}
}
+
uint32_t GetDataFormatSupport(DataFormat fmt) const override;
void SetErrorCallback(ErrorCallbackFn callback, void *userdata) override {
@@ -601,6 +602,78 @@ OpenGLContext::OpenGLContext() {
// TODO: Should this workaround be removed for newer devices/drivers?
bugs_.Infest(Bugs::PVR_GENMIPMAP_HEIGHT_GREATER);
}
+
+ shaderLanguageDesc_.Init(GLSL_1xx);
+
+ // Detect shader language features.
+ if (gl_extensions.IsGLES) {
+ if (gl_extensions.GLES3) {
+ shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
+ shaderLanguageDesc_.glslVersionNumber = 300; // GLSL ES 3.0
+ shaderLanguageDesc_.fragColor0 = "fragColor0";
+ shaderLanguageDesc_.texture = "texture";
+ shaderLanguageDesc_.glslES30 = true;
+ shaderLanguageDesc_.bitwiseOps = true;
+ shaderLanguageDesc_.texelFetch = "texelFetch";
+ shaderLanguageDesc_.varying_vs = "out";
+ shaderLanguageDesc_.varying_fs = "in";
+ shaderLanguageDesc_.attribute = "in";
+ } else {
+ shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
+ shaderLanguageDesc_.glslVersionNumber = 100; // GLSL ES 1.0
+ if (gl_extensions.EXT_gpu_shader4) {
+ shaderLanguageDesc_.bitwiseOps = true;
+ shaderLanguageDesc_.texelFetch = "texelFetch2D";
+ }
+ if (gl_extensions.EXT_blend_func_extended) {
+ // Oldy moldy GLES, so use the fixed output name.
+ shaderLanguageDesc_.fragColor1 = "gl_SecondaryFragColorEXT";
+ }
+ }
+ } else {
+ if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) {
+ if (gl_extensions.VersionGEThan(3, 3, 0)) {
+ shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_3xx;
+ shaderLanguageDesc_.glslVersionNumber = 330;
+ shaderLanguageDesc_.fragColor0 = "fragColor0";
+ shaderLanguageDesc_.texture = "texture";
+ shaderLanguageDesc_.glslES30 = true;
+ shaderLanguageDesc_.bitwiseOps = true;
+ shaderLanguageDesc_.texelFetch = "texelFetch";
+ shaderLanguageDesc_.varying_vs = "out";
+ shaderLanguageDesc_.varying_fs = "in";
+ shaderLanguageDesc_.attribute = "in";
+ } else if (gl_extensions.VersionGEThan(3, 0, 0)) {
+ shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
+ shaderLanguageDesc_.glslVersionNumber = 130;
+ shaderLanguageDesc_.fragColor0 = "fragColor0";
+ shaderLanguageDesc_.bitwiseOps = true;
+ shaderLanguageDesc_.texelFetch = "texelFetch";
+ } else {
+ shaderLanguageDesc_.shaderLanguage = ShaderLanguage::GLSL_1xx;
+ shaderLanguageDesc_.glslVersionNumber = 110;
+ if (gl_extensions.EXT_gpu_shader4) {
+ shaderLanguageDesc_.bitwiseOps = true;
+ shaderLanguageDesc_.texelFetch = "texelFetch2D";
+ }
+ }
+ }
+ }
+
+ if (gl_extensions.IsGLES && gl_extensions.GLES3) {
+ caps_.framebufferFetchSupported = (gl_extensions.EXT_shader_framebuffer_fetch || gl_extensions.NV_shader_framebuffer_fetch || gl_extensions.ARM_shader_framebuffer_fetch);
+ if (gl_extensions.EXT_shader_framebuffer_fetch) {
+ shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
+ shaderLanguageDesc_.lastFragData = "gl_LastFragData[0]";
+ } else if (gl_extensions.NV_shader_framebuffer_fetch) {
+ // GL_NV_shader_framebuffer_fetch is available on mobile platform and ES 2.0 only but not on desktop.
+ shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_NV_shader_framebuffer_fetch : require";
+ shaderLanguageDesc_.lastFragData = "gl_LastFragData[0]";
+ } else if (gl_extensions.ARM_shader_framebuffer_fetch) {
+ shaderLanguageDesc_.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require";
+ shaderLanguageDesc_.lastFragData = "gl_LastFragColorARM";
+ }
+ }
}
OpenGLContext::~OpenGLContext() {
@@ -735,13 +808,16 @@ OpenGLTexture::~OpenGLTexture() {
class OpenGLFramebuffer : public Framebuffer {
public:
- OpenGLFramebuffer(GLRenderManager *render) : render_(render) {}
+ OpenGLFramebuffer(GLRenderManager *render, GLRFramebuffer *framebuffer) : render_(render), framebuffer_(framebuffer) {
+ width_ = framebuffer->width;
+ height_ = framebuffer->height;
+ }
~OpenGLFramebuffer() {
- render_->DeleteFramebuffer(framebuffer);
+ render_->DeleteFramebuffer(framebuffer_);
}
GLRenderManager *render_;
- GLRFramebuffer *framebuffer = nullptr;
+ GLRFramebuffer *framebuffer_ = nullptr;
};
// TODO: SSE/NEON optimize, and move to ColorConv.cpp.
@@ -843,7 +919,7 @@ bool OpenGLContext::CopyFramebufferToMemorySync(Framebuffer *src, int channelBit
aspect |= GL_DEPTH_BUFFER_BIT;
if (channelBits & FB_STENCIL_BIT)
aspect |= GL_STENCIL_BUFFER_BIT;
- renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, tag);
+ renderManager_.CopyFramebufferToMemorySync(fb ? fb->framebuffer_ : nullptr, aspect, x, y, w, h, dataFormat, (uint8_t *)pixels, pixelStride, tag);
return true;
}
@@ -1239,8 +1315,8 @@ void OpenGLInputLayout::Compile(const InputLayoutDesc &desc) {
Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) {
CheckGLExtensions();
- OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_);
- fbo->framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil);
+ GLRFramebuffer *framebuffer = renderManager_.CreateFramebuffer(desc.width, desc.height, desc.z_stencil);
+ OpenGLFramebuffer *fbo = new OpenGLFramebuffer(&renderManager_, framebuffer);
return fbo;
}
@@ -1250,7 +1326,7 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const Render
GLRRenderPassAction depth = (GLRRenderPassAction)rp.depth;
GLRRenderPassAction stencil = (GLRRenderPassAction)rp.stencil;
- renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag);
+ renderManager_.BindFramebufferAsRenderTarget(fb ? fb->framebuffer_ : nullptr, color, depth, stencil, rp.clearColor, rp.clearDepth, rp.clearStencil, tag);
}
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, const char *tag) {
@@ -1266,7 +1342,7 @@ void OpenGLContext::CopyFramebufferImage(Framebuffer *fbsrc, int srcLevel, int s
if (channelBits & FB_STENCIL_BIT)
aspect |= GL_STENCIL_BUFFER_BIT;
}
- renderManager_.CopyFramebuffer(src->framebuffer, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer, GLOffset2D{ dstX, dstY }, aspect, tag);
+ renderManager_.CopyFramebuffer(src->framebuffer_, GLRect2D{ srcX, srcY, width, height }, dst->framebuffer_, GLOffset2D{ dstX, dstY }, aspect, tag);
}
bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *fbdst, int dstX1, int dstY1, int dstX2, int dstY2, int channels, FBBlitFilter linearFilter, const char *tag) {
@@ -1280,7 +1356,7 @@ bool OpenGLContext::BlitFramebuffer(Framebuffer *fbsrc, int srcX1, int srcY1, in
if (channels & FB_STENCIL_BIT)
aspect |= GL_STENCIL_BUFFER_BIT;
- renderManager_.BlitFramebuffer(src->framebuffer, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR, tag);
+ renderManager_.BlitFramebuffer(src->framebuffer_, GLRect2D{ srcX1, srcY1, srcX2 - srcX1, srcY2 - srcY1 }, dst->framebuffer_, GLRect2D{ dstX1, dstY1, dstX2 - dstX1, dstY2 - dstY1 }, aspect, linearFilter == FB_BLIT_LINEAR, tag);
return true;
}
@@ -1294,14 +1370,14 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh
aspect |= GL_DEPTH_BUFFER_BIT;
if (channelBit & FB_STENCIL_BIT)
aspect |= GL_STENCIL_BUFFER_BIT;
- renderManager_.BindFramebufferAsTexture(fb->framebuffer, binding, aspect, color);
+ renderManager_.BindFramebufferAsTexture(fb->framebuffer_, binding, aspect, color);
}
void OpenGLContext::GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) {
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
if (fb) {
- *w = fb->framebuffer->width;
- *h = fb->framebuffer->height;
+ *w = fb->Width();
+ *h = fb->Height();
} else {
*w = targetWidth_;
*h = targetHeight_;
diff --git a/Common/GPU/Shader.cpp b/Common/GPU/Shader.cpp
index 79684874c3..f4bfe96b69 100644
--- a/Common/GPU/Shader.cpp
+++ b/Common/GPU/Shader.cpp
@@ -1 +1,81 @@
#include "Common/GPU/Shader.h"
+
+ShaderLanguageDesc::ShaderLanguageDesc(ShaderLanguage lang) {
+ Init(lang);
+}
+
+void ShaderLanguageDesc::Init(ShaderLanguage lang) {
+ shaderLanguage = lang;
+ switch (lang) {
+ case GLSL_1xx:
+ // Just used in the shader test, and as a basis for the others in DetectShaderLanguage.
+ glslVersionNumber = 110;
+ attribute = "attribute";
+ varying_vs = "varying";
+ varying_fs = "varying";
+ fragColor0 = "gl_FragColor";
+ fragColor1 = "fragColor1";
+ texture = "texture2D";
+ texelFetch = nullptr;
+ bitwiseOps = false;
+ lastFragData = nullptr;
+ gles = false;
+ forceMatrix4x4 = true;
+ break;
+ case GLSL_3xx:
+ // Just used in the shader test.
+ glslVersionNumber = 300; // GLSL ES 3.0
+ varying_vs = "out";
+ varying_fs = "in";
+ attribute = "in";
+ fragColor0 = "fragColor0";
+ fragColor1 = "fragColor1";
+ texture = "texture";
+ texelFetch = nullptr;
+ bitwiseOps = false;
+ lastFragData = nullptr;
+ gles = false;
+ forceMatrix4x4 = true;
+ glslES30 = true;
+ bitwiseOps = true;
+ texelFetch = "texelFetch";
+ break;
+ case GLSL_VULKAN:
+ fragColor0 = "fragColor0";
+ fragColor1 = "fragColor1";
+ varying_fs = "in";
+ varying_vs = "out";
+ attribute = "in";
+ bitwiseOps = true;
+ framebufferFetchExtension = nullptr;
+ gles = false;
+ glslES30 = true;
+ glslVersionNumber = 450;
+ lastFragData = nullptr;
+ texture = "texture";
+ texelFetch = "texelFetch";
+ forceMatrix4x4 = false;
+ coefsFromBuffers = true;
+ break;
+ case HLSL_D3D9:
+ case HLSL_D3D11:
+ fragColor0 = "outfragment.target";
+ fragColor1 = "outfragment.target1";
+ varying_fs = "in";
+ varying_vs = "out";
+ attribute = "in";
+ bitwiseOps = lang == HLSL_D3D11;
+ framebufferFetchExtension = nullptr;
+ gles = false;
+ glslES30 = true;
+ glslVersionNumber = 0;
+ lastFragData = nullptr;
+ texture = "texture";
+ texelFetch = "texelFetch";
+ forceMatrix4x4 = false;
+ coefsFromBuffers = true;
+ vsOutPrefix = "Out.";
+ break;
+ }
+}
+
diff --git a/Common/GPU/Shader.h b/Common/GPU/Shader.h
index e5adc8b514..d574cd4738 100644
--- a/Common/GPU/Shader.h
+++ b/Common/GPU/Shader.h
@@ -23,8 +23,11 @@ enum class ShaderStage {
};
struct ShaderLanguageDesc {
+ ShaderLanguageDesc() {}
explicit ShaderLanguageDesc(ShaderLanguage lang);
+ void Init(ShaderLanguage lang);
+
int glslVersionNumber = 0;
ShaderLanguage shaderLanguage;
bool gles = false;
diff --git a/Common/GPU/Vulkan/thin3d_vulkan.cpp b/Common/GPU/Vulkan/thin3d_vulkan.cpp
index 5f5ad3b808..eabd2b0a72 100644
--- a/Common/GPU/Vulkan/thin3d_vulkan.cpp
+++ b/Common/GPU/Vulkan/thin3d_vulkan.cpp
@@ -497,7 +497,6 @@ public:
void InvalidateCachedState() override;
private:
-
VulkanTexture *GetNullTexture();
VulkanContext *vulkan_ = nullptr;
@@ -760,6 +759,8 @@ bool VKTexture::Create(VkCommandBuffer cmd, VulkanPushBuffer *push, const Textur
VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
: vulkan_(vulkan), caps_{}, renderManager_(vulkan) {
+ shaderLanguageDesc_.Init(GLSL_VULKAN);
+
caps_.anisoSupported = vulkan->GetDeviceFeatures().enabled.samplerAnisotropy != 0;
caps_.geometryShaderSupported = vulkan->GetDeviceFeatures().enabled.geometryShader != 0;
caps_.tesselationShaderSupported = vulkan->GetDeviceFeatures().enabled.tessellationShader != 0;
@@ -780,8 +781,7 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
case VULKAN_VENDOR_NVIDIA: caps_.vendor = GPUVendor::VENDOR_NVIDIA; break;
case VULKAN_VENDOR_QUALCOMM: caps_.vendor = GPUVendor::VENDOR_QUALCOMM; break;
case VULKAN_VENDOR_INTEL: caps_.vendor = GPUVendor::VENDOR_INTEL; break;
- default:
- caps_.vendor = GPUVendor::VENDOR_UNKNOWN;
+ default: caps_.vendor = GPUVendor::VENDOR_UNKNOWN; break;
}
if (caps_.vendor == GPUVendor::VENDOR_QUALCOMM) {
@@ -1448,7 +1448,11 @@ uint32_t VKContext::GetDataFormatSupport(DataFormat fmt) const {
// use this frame's init command buffer.
class VKFramebuffer : public Framebuffer {
public:
- VKFramebuffer(VKRFramebuffer *fb) : buf_(fb) { _assert_msg_(fb, "Null fb in VKFramebuffer constructor"); }
+ VKFramebuffer(VKRFramebuffer *fb) : buf_(fb) {
+ _assert_msg_(fb, "Null fb in VKFramebuffer constructor");
+ width_ = fb->width;
+ height_ = fb->height;
+ }
~VKFramebuffer() {
_assert_msg_(buf_, "Null buf_ in VKFramebuffer - double delete?");
buf_->vulkan_->Delete().QueueCallback([](void *fb) {
diff --git a/Common/GPU/thin3d.h b/Common/GPU/thin3d.h
index 1e7ddf0e75..055cb93e1e 100644
--- a/Common/GPU/thin3d.h
+++ b/Common/GPU/thin3d.h
@@ -347,6 +347,10 @@ public:
class Framebuffer : public RefCountedObject {
public:
+ int Width() { return width_; }
+ int Height() { return height_; }
+protected:
+ int width_ = -1, height_ = -1;
};
class Buffer : public RefCountedObject {
@@ -359,7 +363,7 @@ public:
int Height() { return height_; }
int Depth() { return depth_; }
protected:
- int width_, height_, depth_;
+ int width_ = -1, height_ = -1, depth_ = -1;
};
struct BindingDesc {
@@ -496,6 +500,7 @@ struct DeviceCaps {
bool framebufferBlitSupported;
bool framebufferDepthCopySupported;
bool framebufferDepthBlitSupported;
+ bool framebufferFetchSupported;
std::string deviceName; // The device name to use when creating the thin3d context, to get the same one.
};
@@ -548,6 +553,11 @@ public:
virtual std::vector GetExtensionList() const { return std::vector(); }
virtual std::vector GetDeviceList() const { return std::vector(); }
+ // Describes the primary shader language that this implementation prefers.
+ const ShaderLanguageDesc &GetShaderLanguageDesc() {
+ return shaderLanguageDesc_;
+ }
+
virtual uint32_t GetSupportedShaderLanguages() const = 0;
virtual void SetErrorCallback(ErrorCallbackFn callback, void *userdata) {}
@@ -663,6 +673,8 @@ protected:
ShaderModule *vsPresets_[VS_MAX_PRESET];
ShaderModule *fsPresets_[FS_MAX_PRESET];
+ ShaderLanguageDesc shaderLanguageDesc_;
+
int targetWidth_;
int targetHeight_;
diff --git a/Core/CoreParameter.h b/Core/CoreParameter.h
index a4e542bf02..abfb9e40e6 100644
--- a/Core/CoreParameter.h
+++ b/Core/CoreParameter.h
@@ -66,11 +66,12 @@ struct CoreParameter {
std::string *collectEmuLog = nullptr;
bool headLess; // Try to avoid messageboxes etc
- // Internal PSP resolution
+ // Internal PSP rendering resolution and scale factor.
+ int renderScaleFactor;
int renderWidth;
int renderHeight;
- // Actual pixel output resolution (for use by glViewport and the like)
+ // Actual output resolution in pixels.
int pixelWidth;
int pixelHeight;
diff --git a/GPU/Common/FramebufferManagerCommon.cpp b/GPU/Common/FramebufferManagerCommon.cpp
index b83bef2098..6d0744dea9 100644
--- a/GPU/Common/FramebufferManagerCommon.cpp
+++ b/GPU/Common/FramebufferManagerCommon.cpp
@@ -77,6 +77,7 @@ bool FramebufferManagerCommon::UpdateSize() {
renderWidth_ = (float)PSP_CoreParameter().renderWidth;
renderHeight_ = (float)PSP_CoreParameter().renderHeight;
+ renderScaleFactor_ = (float)PSP_CoreParameter().renderScaleFactor;
pixelWidth_ = PSP_CoreParameter().pixelWidth;
pixelHeight_ = PSP_CoreParameter().pixelHeight;
bloomHack_ = g_Config.iBloomHack;
@@ -340,14 +341,6 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
}
}
- float renderWidthFactor = renderWidth_ / 480.0f;
- float renderHeightFactor = renderHeight_ / 272.0f;
-
- if (PSP_CoreParameter().compat.flags().Force04154000Download && params.fb_address == 0x04154000) {
- renderWidthFactor = 1.0;
- renderHeightFactor = 1.0;
- }
-
// None found? Create one.
if (!vfb) {
vfb = new VirtualFramebuffer{};
@@ -356,28 +349,28 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame
vfb->fb_stride = params.fb_stride;
vfb->z_address = params.z_address;
vfb->z_stride = params.z_stride;
+
+ // The other width/height parameters are set in ResizeFramebufFBO below.
vfb->width = drawing_width;
vfb->height = drawing_height;
vfb->newWidth = drawing_width;
vfb->newHeight = drawing_height;
vfb->lastFrameNewSize = gpuStats.numFlips;
- vfb->renderWidth = (u16)(drawing_width * renderWidthFactor);
- vfb->renderHeight = (u16)(drawing_height * renderHeightFactor);
- vfb->bufferWidth = drawing_width;
- vfb->bufferHeight = drawing_height;
vfb->format = params.fmt;
vfb->drawnFormat = params.fmt;
vfb->usageFlags = FB_USAGE_RENDERTARGET;
- SetColorUpdated(vfb, skipDrawReason);
u32 byteSize = ColorBufferByteSize(vfb);
if (Memory::IsVRAMAddress(params.fb_address) && params.fb_address + byteSize > framebufRangeEnd_) {
framebufRangeEnd_ = params.fb_address + byteSize;
}
+ // This is where we actually create the framebuffer. The true is "force".
ResizeFramebufFBO(vfb, drawing_width, drawing_height, true);
NotifyRenderFramebufferCreated(vfb);
+ SetColorUpdated(vfb, skipDrawReason);
+
INFO_LOG(FRAMEBUF, "Creating FBO for %08x (z: %08x) : %i x %i x %i", vfb->fb_address, vfb->z_address, vfb->width, vfb->height, vfb->format);
vfb->last_frame_render = gpuStats.numFlips;
@@ -1046,6 +1039,7 @@ void FramebufferManagerCommon::DecimateFBOs() {
}
}
+// Requires width/height to be set already.
void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, int h, bool force, bool skipCopy) {
_dbg_assert_(w > 0);
_dbg_assert_(h > 0);
@@ -1067,7 +1061,32 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
vfb->bufferHeight = std::max((int)vfb->bufferHeight, h);
}
- SetRenderSize(vfb);
+ bool force1x = false;
+ switch (bloomHack_) {
+ case 1:
+ force1x = vfb->bufferWidth <= 128 || vfb->bufferHeight <= 64;
+ break;
+ case 2:
+ force1x = vfb->bufferWidth <= 256 || vfb->bufferHeight <= 128;
+ break;
+ case 3:
+ force1x = vfb->bufferWidth < 480 || vfb->bufferWidth > 800 || vfb->bufferHeight < 272; // GOW uses 864x272
+ break;
+ }
+
+ if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000) {
+ force1x = true;
+ }
+
+ if (force1x && g_Config.iInternalResolution != 1) {
+ vfb->renderScaleFactor = 1.0f;
+ vfb->renderWidth = vfb->bufferWidth;
+ vfb->renderHeight = vfb->bufferHeight;
+ } else {
+ vfb->renderScaleFactor = renderScaleFactor_;
+ vfb->renderWidth = (u16)(vfb->bufferWidth * renderScaleFactor_);
+ vfb->renderHeight = (u16)(vfb->bufferHeight * renderScaleFactor_);
+ }
// During hardware rendering, we always render at full color depth even if the game wouldn't on real hardware.
// It's not worth the trouble trying to support lower bit-depth rendering, just
@@ -1655,35 +1674,6 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS
}
}
-void FramebufferManagerCommon::SetRenderSize(VirtualFramebuffer *vfb) {
- float renderWidthFactor = renderWidth_ / 480.0f;
- float renderHeightFactor = renderHeight_ / 272.0f;
- bool force1x = false;
- switch (bloomHack_) {
- case 1:
- force1x = vfb->bufferWidth <= 128 || vfb->bufferHeight <= 64;
- break;
- case 2:
- force1x = vfb->bufferWidth <= 256 || vfb->bufferHeight <= 128;
- break;
- case 3:
- force1x = vfb->bufferWidth < 480 || vfb->bufferWidth > 800 || vfb->bufferHeight < 272; // GOW uses 864x272
- break;
- }
-
- if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x04154000) {
- force1x = true;
- }
-
- if (force1x && g_Config.iInternalResolution != 1) {
- vfb->renderWidth = vfb->bufferWidth;
- vfb->renderHeight = vfb->bufferHeight;
- } else {
- vfb->renderWidth = (u16)(vfb->bufferWidth * renderWidthFactor);
- vfb->renderHeight = (u16)(vfb->bufferHeight * renderHeightFactor);
- }
-}
-
void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) {
VirtualFramebuffer *vfb = currentRenderVfb_;
if (vfb) {
@@ -1695,10 +1685,11 @@ void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) {
void FramebufferManagerCommon::Resized() {
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
- int w, h;
- presentation_->CalculateRenderResolution(&w, &h, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_);
+ int w, h, scaleFactor;
+ presentation_->CalculateRenderResolution(&w, &h, &scaleFactor, &postShaderIsUpscalingFilter_, &postShaderIsSupersampling_);
PSP_CoreParameter().renderWidth = w;
PSP_CoreParameter().renderHeight = h;
+ PSP_CoreParameter().renderScaleFactor = scaleFactor;
if (UpdateSize()) {
DestroyAllFBOs();
@@ -1736,6 +1727,11 @@ void FramebufferManagerCommon::DestroyAllFBOs() {
tempFB.second.fbo->Release();
}
tempFBOs_.clear();
+
+ for (auto iter : fbosToDelete_) {
+ iter->Release();
+ }
+ fbosToDelete_.clear();
}
Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u16 h) {
diff --git a/GPU/Common/FramebufferManagerCommon.h b/GPU/Common/FramebufferManagerCommon.h
index 905bdaed14..3df8b69acf 100644
--- a/GPU/Common/FramebufferManagerCommon.h
+++ b/GPU/Common/FramebufferManagerCommon.h
@@ -61,21 +61,24 @@ struct VirtualFramebuffer {
u16 width;
u16 height;
- // renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions.
- // The physical buffer may be larger than renderWidth/renderHeight.
- u16 renderWidth;
- u16 renderHeight;
-
- // bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than width/height.
+ // bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than or equal to width/height.
// Actual physical buffer is this size times the render resolution multiplier.
// The buffer may be used to render a width or height from 0 to these values without being recreated.
u16 bufferWidth;
u16 bufferHeight;
+ // renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions.
+ // The physical buffer may be larger than renderWidth/renderHeight.
+ u16 renderWidth;
+ u16 renderHeight;
+
+ float renderScaleFactor;
+
u16 usageFlags;
u16 newWidth;
u16 newHeight;
+
int lastFrameNewSize;
Draw::Framebuffer *fbo;
@@ -396,9 +399,10 @@ protected:
bool gameUsesSequentialCopies_ = false;
- // Sampled in BeginFrame for safety.
+ // Sampled in BeginFrame/UpdateSize for safety.
float renderWidth_ = 0.0f;
float renderHeight_ = 0.0f;
+ float renderScaleFactor_ = 1.0f;
int pixelWidth_;
int pixelHeight_;
int bloomHack_ = 0;
diff --git a/GPU/Common/PresentationCommon.cpp b/GPU/Common/PresentationCommon.cpp
index e4b966ff6f..58233a6d29 100644
--- a/GPU/Common/PresentationCommon.cpp
+++ b/GPU/Common/PresentationCommon.cpp
@@ -729,7 +729,7 @@ void PresentationCommon::CopyToOutput(OutputFlags flags, int uvRotation, float u
draw_->BindPipeline(nullptr);
}
-void PresentationCommon::CalculateRenderResolution(int *width, int *height, bool *upscaling, bool *ssaa) {
+void PresentationCommon::CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa) {
// Check if postprocessing shader is doing upscaling as it requires native resolution
std::vector shaderInfo;
if (!g_Config.vPostShaderNames.empty() && g_Config.vPostShaderNames[0] != "Off") {
@@ -776,4 +776,6 @@ void PresentationCommon::CalculateRenderResolution(int *width, int *height, bool
*width = 480 * zoom;
*height = 272 * zoom;
}
+
+ *scaleFactor = zoom;
}
diff --git a/GPU/Common/PresentationCommon.h b/GPU/Common/PresentationCommon.h
index 0102c3fbcf..959e516d5f 100644
--- a/GPU/Common/PresentationCommon.h
+++ b/GPU/Common/PresentationCommon.h
@@ -100,7 +100,7 @@ public:
void SourceFramebuffer(Draw::Framebuffer *fb, int bufferWidth, int bufferHeight);
void CopyToOutput(OutputFlags flags, int uvRotation, float u0, float v0, float u1, float v1);
- void CalculateRenderResolution(int *width, int *height, bool *upscaling, bool *ssaa);
+ void CalculateRenderResolution(int *width, int *height, int *scaleFactor, bool *upscaling, bool *ssaa);
protected:
void CreateDeviceObjects();
diff --git a/GPU/Common/ShaderCommon.cpp b/GPU/Common/ShaderCommon.cpp
index 45ba5ab357..360e7f9d8b 100644
--- a/GPU/Common/ShaderCommon.cpp
+++ b/GPU/Common/ShaderCommon.cpp
@@ -101,79 +101,3 @@ void init_resources(TBuiltInResource &Resources) {
Resources.limits.generalVariableIndexing = 1;
Resources.limits.generalConstantMatrixVectorIndexing = 1;
}
-
-ShaderLanguageDesc::ShaderLanguageDesc(ShaderLanguage lang) {
- shaderLanguage = lang;
- switch (lang) {
- case GLSL_1xx:
- // Just used in the shader test, and as a basis for the others in DetectShaderLanguage.
- glslVersionNumber = 110;
- attribute = "attribute";
- varying_vs = "varying";
- varying_fs = "varying";
- fragColor0 = "gl_FragColor";
- fragColor1 = "fragColor1";
- texture = "texture2D";
- texelFetch = nullptr;
- bitwiseOps = false;
- lastFragData = nullptr;
- gles = false;
- forceMatrix4x4 = true;
- break;
- case GLSL_3xx:
- // Just used in the shader test.
- glslVersionNumber = 300; // GLSL ES 3.0
- varying_vs = "out";
- varying_fs = "in";
- attribute = "in";
- fragColor0 = "fragColor0";
- fragColor1 = "fragColor1";
- texture = "texture";
- texelFetch = nullptr;
- bitwiseOps = false;
- lastFragData = nullptr;
- gles = false;
- forceMatrix4x4 = true;
- glslES30 = true;
- bitwiseOps = true;
- texelFetch = "texelFetch";
- break;
- case GLSL_VULKAN:
- fragColor0 = "fragColor0";
- fragColor1 = "fragColor1";
- varying_fs = "in";
- varying_vs = "out";
- attribute = "in";
- bitwiseOps = true;
- framebufferFetchExtension = nullptr;
- gles = false;
- glslES30 = true;
- glslVersionNumber = 450;
- lastFragData = nullptr;
- texture = "texture";
- texelFetch = "texelFetch";
- forceMatrix4x4 = false;
- coefsFromBuffers = true;
- break;
- case HLSL_D3D9:
- case HLSL_D3D11:
- fragColor0 = "outfragment.target";
- fragColor1 = "outfragment.target1";
- varying_fs = "in";
- varying_vs = "out";
- attribute = "in";
- bitwiseOps = lang == HLSL_D3D11;
- framebufferFetchExtension = nullptr;
- gles = false;
- glslES30 = true;
- glslVersionNumber = 0;
- lastFragData = nullptr;
- texture = "texture";
- texelFetch = "texelFetch";
- forceMatrix4x4 = false;
- coefsFromBuffers = true;
- vsOutPrefix = "Out.";
- break;
- }
-}
-
diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp
index 5e2e716e32..2a90aaa4e4 100644
--- a/GPU/D3D11/FramebufferManagerD3D11.cpp
+++ b/GPU/D3D11/FramebufferManagerD3D11.cpp
@@ -420,8 +420,8 @@ void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
return;
}
- float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth;
- float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight;
+ float srcXFactor = src->renderScaleFactor;
+ float srcYFactor = src->renderScaleFactor;
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@@ -431,8 +431,8 @@ void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
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;
+ float dstXFactor = dst->renderScaleFactor;
+ float dstYFactor = dst->renderScaleFactor;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;
diff --git a/GPU/D3D11/ShaderManagerD3D11.cpp b/GPU/D3D11/ShaderManagerD3D11.cpp
index 88730eec70..255c547ee9 100644
--- a/GPU/D3D11/ShaderManagerD3D11.cpp
+++ b/GPU/D3D11/ShaderManagerD3D11.cpp
@@ -89,7 +89,7 @@ std::string D3D11VertexShader::GetShaderString(DebugShaderStringType type) const
}
ShaderManagerD3D11::ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel)
- : ShaderManagerCommon(draw), device_(device), context_(context), featureLevel_(featureLevel), compat_(ShaderLanguage::HLSL_D3D11) {
+ : ShaderManagerCommon(draw), device_(device), context_(context), featureLevel_(featureLevel) {
codeBuffer_ = new char[16384];
memset(&ub_base, 0, sizeof(ub_base));
memset(&ub_lights, 0, sizeof(ub_lights));
@@ -210,7 +210,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
std::string genErrorString;
uint32_t attrMask;
uint64_t uniformMask;
- GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &genErrorString);
+ GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString);
vs = new D3D11VertexShader(device_, featureLevel_, VSID, codeBuffer_, vertType, useHWTransform);
vsCache_[VSID] = vs;
} else {
@@ -224,7 +224,7 @@ void ShaderManagerD3D11::GetShaders(int prim, u32 vertType, D3D11VertexShader **
// Fragment shader not in cache. Let's compile it.
std::string genErrorString;
uint64_t uniformMask;
- GenerateFragmentShader(FSID, codeBuffer_, compat_, &uniformMask, &genErrorString);
+ GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &genErrorString);
fs = new D3D11FragmentShader(device_, featureLevel_, FSID, codeBuffer_, useHWTransform);
fsCache_[FSID] = fs;
} else {
diff --git a/GPU/D3D11/ShaderManagerD3D11.h b/GPU/D3D11/ShaderManagerD3D11.h
index 140a9a3656..fe21710ad9 100644
--- a/GPU/D3D11/ShaderManagerD3D11.h
+++ b/GPU/D3D11/ShaderManagerD3D11.h
@@ -110,7 +110,6 @@ private:
ID3D11Device *device_;
ID3D11DeviceContext *context_;
D3D_FEATURE_LEVEL featureLevel_;
- ShaderLanguageDesc compat_;
typedef std::map FSCache;
FSCache fsCache_;
diff --git a/GPU/Directx9/FramebufferManagerDX9.cpp b/GPU/Directx9/FramebufferManagerDX9.cpp
index 776cdcf7f3..951406c80d 100644
--- a/GPU/Directx9/FramebufferManagerDX9.cpp
+++ b/GPU/Directx9/FramebufferManagerDX9.cpp
@@ -383,8 +383,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
return;
}
- float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth;
- float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight;
+ float srcXFactor = (float)src->renderScaleFactor;
+ float srcYFactor = (float)src->renderScaleFactor;
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@@ -394,8 +394,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
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;
+ float dstXFactor = (float)dst->renderScaleFactor;
+ float dstYFactor = (float)dst->renderScaleFactor;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;
diff --git a/GPU/Directx9/ShaderManagerDX9.cpp b/GPU/Directx9/ShaderManagerDX9.cpp
index 4aafbcb290..bb423ca233 100644
--- a/GPU/Directx9/ShaderManagerDX9.cpp
+++ b/GPU/Directx9/ShaderManagerDX9.cpp
@@ -502,7 +502,7 @@ void ShaderManagerDX9::VSUpdateUniforms(u64 dirtyUniforms) {
}
ShaderManagerDX9::ShaderManagerDX9(Draw::DrawContext *draw, LPDIRECT3DDEVICE9 device)
- : ShaderManagerCommon(draw), device_(device), compat_(HLSL_D3D9) {
+ : ShaderManagerCommon(draw), device_(device) {
codeBuffer_ = new char[32768];
}
@@ -582,7 +582,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
std::string genErrorString;
uint32_t attrMask;
uint64_t uniformMask;
- if (GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &genErrorString)) {
+ if (GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString)) {
vs = new VSShader(device_, VSID, codeBuffer_, useHWTransform);
}
if (!vs || vs->Failed()) {
@@ -607,7 +607,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
// Can still work with software transform.
uint32_t attrMask;
uint64_t uniformMask;
- bool success = GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &genErrorString);
+ bool success = GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &genErrorString);
_assert_(success);
vs = new VSShader(device_, VSID, codeBuffer_, false);
}
@@ -624,7 +624,7 @@ VSShader *ShaderManagerDX9::ApplyShader(bool useHWTransform, bool useHWTessellat
// Fragment shader not in cache. Let's compile it.
std::string errorString;
uint64_t uniformMask;
- bool success = GenerateFragmentShader(FSID, codeBuffer_, compat_, &uniformMask, &errorString);
+ bool success = GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &errorString);
// We're supposed to handle all possible cases.
_assert_(success);
fs = new PSShader(device_, FSID, codeBuffer_);
diff --git a/GPU/Directx9/ShaderManagerDX9.h b/GPU/Directx9/ShaderManagerDX9.h
index 8e132e2a31..d8062ef881 100644
--- a/GPU/Directx9/ShaderManagerDX9.h
+++ b/GPU/Directx9/ShaderManagerDX9.h
@@ -111,7 +111,6 @@ private:
void Clear();
LPDIRECT3DDEVICE9 device_;
- ShaderLanguageDesc compat_;
FShaderID lastFSID_;
VShaderID lastVSID_;
diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp
index c0fd949930..6d625b2de5 100644
--- a/GPU/GLES/FramebufferManagerGLES.cpp
+++ b/GPU/GLES/FramebufferManagerGLES.cpp
@@ -315,8 +315,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
bool useBlit = gstate_c.Supports(GPU_SUPPORTS_FRAMEBUFFER_BLIT);
- float srcXFactor = useBlit ? (float)src->renderWidth / (float)src->bufferWidth : 1.0f;
- float srcYFactor = useBlit ? (float)src->renderHeight / (float)src->bufferHeight : 1.0f;
+ float srcXFactor = useBlit ? src->renderScaleFactor : 1.0f;
+ float srcYFactor = useBlit ? src->renderScaleFactor : 1.0f;
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@@ -326,8 +326,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
int srcY1 = srcY * srcYFactor;
int srcY2 = (srcY + h) * srcYFactor;
- float dstXFactor = useBlit ? (float)dst->renderWidth / (float)dst->bufferWidth : 1.0f;
- float dstYFactor = useBlit ? (float)dst->renderHeight / (float)dst->bufferHeight : 1.0f;
+ float dstXFactor = useBlit ? dst->renderScaleFactor : 1.0f;
+ float dstYFactor = useBlit ? dst->renderScaleFactor : 1.0f;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;
@@ -360,6 +360,8 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
if (useBlit) {
draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST, "BlitFramebuffer");
} else {
+ // TODO: Move this workaround out into thin3d, instead of dirtying up the code here.
+
draw_->BindFramebufferAsRenderTarget(dst->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::KEEP }, "BlitFramebuffer");
draw_->BindFramebufferAsTexture(src->fbo, 0, Draw::FB_COLOR_BIT, 0);
@@ -376,7 +378,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
float srcW = src->bufferWidth;
float srcH = src->bufferHeight;
render_->BindProgram(draw2dprogram_);
- DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST);
+ DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h * dstYFactor, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST);
textureCacheGL_->ForgetLastTexture();
}
diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp
index be3358c959..a8d23c88ba 100644
--- a/GPU/GLES/ShaderManagerGLES.cpp
+++ b/GPU/GLES/ShaderManagerGLES.cpp
@@ -572,95 +572,17 @@ void LinkedShader::UpdateUniforms(u32 vertType, const ShaderID &vsid, bool useBu
}
ShaderManagerGLES::ShaderManagerGLES(Draw::DrawContext *draw)
- : ShaderManagerCommon(draw), compat_(GLSL_1xx), fsCache_(16), vsCache_(16) {
+ : ShaderManagerCommon(draw), fsCache_(16), vsCache_(16) {
render_ = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
codeBuffer_ = new char[16384];
lastFSID_.set_invalid();
lastVSID_.set_invalid();
- DetectShaderLanguage();
}
ShaderManagerGLES::~ShaderManagerGLES() {
delete [] codeBuffer_;
}
-void ShaderManagerGLES::DetectShaderLanguage() {
- ShaderLanguageDesc &compat = compat_;
-
- compat.gles = gl_extensions.IsGLES;
-
- if (compat.gles) {
- if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
- compat.shaderLanguage = ShaderLanguage::GLSL_3xx;
- compat.glslVersionNumber = 300; // GLSL ES 3.0
- compat.fragColor0 = "fragColor0";
- compat.texture = "texture";
- compat.glslES30 = true;
- compat.bitwiseOps = true;
- compat.texelFetch = "texelFetch";
- compat.varying_vs = "out";
- compat.varying_fs = "in";
- compat.attribute = "in";
- } else {
- compat.shaderLanguage = ShaderLanguage::GLSL_1xx;
- compat.glslVersionNumber = 100; // GLSL ES 1.0
- if (gl_extensions.EXT_gpu_shader4) {
- compat.bitwiseOps = true;
- compat.texelFetch = "texelFetch2D";
- }
- if (gl_extensions.EXT_blend_func_extended) {
- // Oldy moldy GLES, so use the fixed output name.
- compat.fragColor1 = "gl_SecondaryFragColorEXT";
- }
- }
- } else {
- if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) {
- if (gl_extensions.VersionGEThan(3, 3, 0)) {
- compat.shaderLanguage = ShaderLanguage::GLSL_3xx;
- compat.glslVersionNumber = 330;
- compat.fragColor0 = "fragColor0";
- compat.texture = "texture";
- compat.glslES30 = true;
- compat.bitwiseOps = true;
- compat.texelFetch = "texelFetch";
- compat.varying_vs = "out";
- compat.varying_fs = "in";
- compat.attribute = "in";
- } else if (gl_extensions.VersionGEThan(3, 0, 0)) {
- compat.shaderLanguage = ShaderLanguage::GLSL_1xx;
- compat.glslVersionNumber = 130;
- compat.fragColor0 = "fragColor0";
- compat.bitwiseOps = true;
- compat.texelFetch = "texelFetch";
- } else {
- compat.shaderLanguage = ShaderLanguage::GLSL_1xx;
- compat.glslVersionNumber = 110;
- if (gl_extensions.EXT_gpu_shader4) {
- compat.bitwiseOps = true;
- compat.texelFetch = "texelFetch2D";
- }
- }
- }
- }
-
- if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
- if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300) && gl_extensions.EXT_shader_framebuffer_fetch) {
- compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
- compat.lastFragData = "fragColor0";
- } else if (gl_extensions.EXT_shader_framebuffer_fetch) {
- compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require";
- compat.lastFragData = "gl_LastFragData[0]";
- } else if (gl_extensions.NV_shader_framebuffer_fetch) {
- // GL_NV_shader_framebuffer_fetch is available on mobile platform and ES 2.0 only but not on desktop.
- compat.framebufferFetchExtension = "#extension GL_NV_shader_framebuffer_fetch : require";
- compat.lastFragData = "gl_LastFragData[0]";
- } else if (gl_extensions.ARM_shader_framebuffer_fetch) {
- compat.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require";
- compat.lastFragData = "gl_LastFragColorARM";
- }
- }
-}
-
void ShaderManagerGLES::Clear() {
DirtyLastShader();
for (auto iter = linkedShaderCache_.begin(); iter != linkedShaderCache_.end(); ++iter) {
@@ -709,7 +631,7 @@ void ShaderManagerGLES::DirtyLastShader() {
Shader *ShaderManagerGLES::CompileFragmentShader(FShaderID FSID) {
uint64_t uniformMask;
std::string errorString;
- if (!GenerateFragmentShader(FSID, codeBuffer_, compat_, &uniformMask, &errorString)) {
+ if (!GenerateFragmentShader(FSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &uniformMask, &errorString)) {
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
return nullptr;
}
@@ -722,7 +644,7 @@ Shader *ShaderManagerGLES::CompileVertexShader(VShaderID VSID) {
uint32_t attrMask;
uint64_t uniformMask;
std::string errorString;
- if (!GenerateVertexShader(VSID, codeBuffer_, compat_, &attrMask, &uniformMask, &errorString)) {
+ if (!GenerateVertexShader(VSID, codeBuffer_, draw_->GetShaderLanguageDesc(), &attrMask, &uniformMask, &errorString)) {
ERROR_LOG(G3D, "Shader gen error: %s", errorString.c_str());
return nullptr;
}
diff --git a/GPU/GLES/ShaderManagerGLES.h b/GPU/GLES/ShaderManagerGLES.h
index 2343f7d508..71e5541631 100644
--- a/GPU/GLES/ShaderManagerGLES.h
+++ b/GPU/GLES/ShaderManagerGLES.h
@@ -170,7 +170,6 @@ private:
void Clear();
Shader *CompileFragmentShader(FShaderID id);
Shader *CompileVertexShader(VShaderID id);
- void DetectShaderLanguage();
struct LinkedShaderCacheEntry {
LinkedShaderCacheEntry(Shader *vs_, Shader *fs_, LinkedShader *ls_)
@@ -183,7 +182,6 @@ private:
typedef std::vector LinkedShaderCache;
GLRenderManager *render_;
- ShaderLanguageDesc compat_;
LinkedShaderCache linkedShaderCache_;
bool lastVShaderSame_;
diff --git a/GPU/Vulkan/FramebufferManagerVulkan.cpp b/GPU/Vulkan/FramebufferManagerVulkan.cpp
index 8acc1cbe2f..d04021ff58 100644
--- a/GPU/Vulkan/FramebufferManagerVulkan.cpp
+++ b/GPU/Vulkan/FramebufferManagerVulkan.cpp
@@ -261,7 +261,6 @@ void FramebufferManagerVulkan::ReformatFramebufferFrom(VirtualFramebuffer *vfb,
// We have to bind here instead of clear, since it can be that no framebuffer is bound.
// The backend can sometimes directly optimize it to a clear.
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP, Draw::RPAction::CLEAR }, "ReformatFramebuffer");
- // draw_->Clear(Draw::FBChannel::FB_COLOR_BIT | Draw::FBChannel::FB_STENCIL_BIT, 0, 0.0f, 0);
// Need to dirty anything that has command buffer dynamic state, in case we started a new pass above.
// Should find a way to feed that information back, maybe... Or simply correct the issue in the rendermanager.
@@ -339,8 +338,10 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
return;
}
- float srcXFactor = (float)src->renderWidth / (float)src->bufferWidth;
- float srcYFactor = (float)src->renderHeight / (float)src->bufferHeight;
+ float srcXFactor = (float)src->renderScaleFactor;
+ float srcYFactor = (float)src->renderScaleFactor;
+
+ // Some games use wrong-format block transfers. Simulate that.
const int srcBpp = src->format == GE_FORMAT_8888 ? 4 : 2;
if (srcBpp != bpp && bpp != 0) {
srcXFactor = (srcXFactor * bpp) / srcBpp;
@@ -350,8 +351,8 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
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;
+ float dstXFactor = (float)dst->renderScaleFactor;
+ float dstYFactor = (float)dst->renderScaleFactor;
const int dstBpp = dst->format == GE_FORMAT_8888 ? 4 : 2;
if (dstBpp != bpp && bpp != 0) {
dstXFactor = (dstXFactor * bpp) / dstBpp;
@@ -367,8 +368,6 @@ void FramebufferManagerVulkan::BlitFramebuffer(VirtualFramebuffer *dst, int dstX
return;
}
- // BlitFramebuffer can clip, but CopyFramebufferImage is more restricted.
- // In case the src goes outside, we just skip the optimization in that case.
const bool sameSize = dstX2 - dstX1 == srcX2 - srcX1 && dstY2 - dstY1 == srcY2 - srcY1;
const bool srcInsideBounds = srcX2 <= src->renderWidth && srcY2 <= src->renderHeight;
const bool dstInsideBounds = dstX2 <= dst->renderWidth && dstY2 <= dst->renderHeight;
diff --git a/headless/Headless.cpp b/headless/Headless.cpp
index fb80436d73..1dc70e488d 100644
--- a/headless/Headless.cpp
+++ b/headless/Headless.cpp
@@ -358,6 +358,7 @@ int main(int argc, const char* argv[])
coreParameter.startBreak = false;
coreParameter.printfEmuLog = !autoCompare;
coreParameter.headLess = true;
+ coreParameter.renderScaleFactor = 1;
coreParameter.renderWidth = 480;
coreParameter.renderHeight = 272;
coreParameter.pixelWidth = 480;