mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
Merge pull request #13629 from hrydgard/move-shader-lang-detect
Move the shader language feature detection to the draw context
This commit is contained in:
25 files changed
+322
-297
No files matched your search
@@ -729,10 +729,10 @@
|
||||
<ClCompile Include="Render\Text\draw_text_win.cpp">
|
||||
<Filter>Render\Text</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GPU\Shader.cpp">
|
||||
<ClCompile Include="GPU\ShaderWriter.cpp">
|
||||
<Filter>GPU</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="GPU\ShaderWriter.cpp">
|
||||
<ClCompile Include="GPU\Shader.cpp">
|
||||
<Filter>GPU</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+13
-1
@@ -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<std::string> GetExtensionList() const { return std::vector<std::string>(); }
|
||||
virtual std::vector<std::string> GetDeviceList() const { return std::vector<std::string>(); }
|
||||
|
||||
// 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_;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<const ShaderInfo *> 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;
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -110,7 +110,6 @@ private:
|
||||
ID3D11Device *device_;
|
||||
ID3D11DeviceContext *context_;
|
||||
D3D_FEATURE_LEVEL featureLevel_;
|
||||
ShaderLanguageDesc compat_;
|
||||
|
||||
typedef std::map<FShaderID, D3D11FragmentShader *> FSCache;
|
||||
FSCache fsCache_;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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_);
|
||||
|
||||
@@ -111,7 +111,6 @@ private:
|
||||
void Clear();
|
||||
|
||||
LPDIRECT3DDEVICE9 device_;
|
||||
ShaderLanguageDesc compat_;
|
||||
|
||||
FShaderID lastFSID_;
|
||||
VShaderID lastVSID_;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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<LinkedShaderCacheEntry> LinkedShaderCache;
|
||||
|
||||
GLRenderManager *render_;
|
||||
ShaderLanguageDesc compat_;
|
||||
LinkedShaderCache linkedShaderCache_;
|
||||
|
||||
bool lastVShaderSame_;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user