Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve support for mipmaps and related headless fixes #9633

Merged
merged 9 commits into from
Apr 23, 2017
2 changes: 1 addition & 1 deletion GPU/Common/TextureCacheCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl
sClamp = gstate.isTexCoordClampedS();
tClamp = gstate.isTexCoordClampedT();

bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001 || (gstate.texlevel & 0xFFFFFF) == 0x100001; // Fix texlevel at 0
bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001; // Fix texlevel at 0
if (IsFakeMipmapChange())
noMip = gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST;

Expand Down
6 changes: 4 additions & 2 deletions GPU/Common/TextureCacheCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,10 @@ struct SamplerCacheKey {
bool magFilt : 1;
bool sClamp : 1;
bool tClamp : 1;
int lodBias : 4;
int maxLevel : 4;
bool lodAuto : 1;
bool : 1;
int8_t lodBias : 8;
int8_t maxLevel : 4;
};
};

Expand Down
26 changes: 23 additions & 3 deletions GPU/D3D11/TextureCacheD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,25 @@ ID3D11SamplerState *SamplerCacheD3D11::GetOrCreateSampler(ID3D11Device *device,
#if PPSSPP_PLATFORM(UWP) && PPSSPP_ARCH(ARM)
// For some reason, can't set MaxLOD on mobile.
samp.MaxLOD = FLT_MAX;
#else
samp.MaxLOD = key.maxLevel;
#endif
samp.MinLOD = -FLT_MAX;
samp.MipLODBias = 0.0f;
#else
if (!key.mipEnable) {
samp.MaxLOD = 0.0f;
samp.MinLOD = 0.0f;
samp.MipLODBias = 0.0f;
} else if (key.lodAuto) {
// Auto selected mip + bias.
samp.MaxLOD = key.maxLevel;
samp.MinLOD = 0.0f;
samp.MipLODBias = (float)key.lodBias / 16.0f;
} else {
// Constant mip at bias.
samp.MaxLOD = (float)key.lodBias / 16.0f;
samp.MinLOD = (float)key.lodBias / 16.0f;
samp.MipLODBias = 0.0f;
}
#endif
samp.ComparisonFunc = D3D11_COMPARISON_NEVER;
for (int i = 0; i < 4; i++) {
samp.BorderColor[i] = 1.0f;
Expand Down Expand Up @@ -169,7 +183,13 @@ void TextureCacheD3D11::UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheK
key.magFilt = magFilt & 1;
key.sClamp = sClamp;
key.tClamp = tClamp;
key.lodBias = (s8)((gstate.texlevel >> 16) & 0xFF);
if (key.lodBias > entry.maxLevel * 16) {
key.lodBias = entry.maxLevel * 16;
}
key.maxLevel = entry.maxLevel;
key.lodAuto = gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_AUTO;
// TODO: GE_TEXLEVEL_MODE_SLOPE

if (entry.framebuffer) {
WARN_LOG_REPORT_ONCE(wrongFramebufAttach, G3D, "Framebuffer still attached in UpdateSamplingParams()?");
Expand Down
2 changes: 2 additions & 0 deletions GPU/Directx9/FramebufferDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,8 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = {
dxstate.texMagFilter.set(D3DTEXF_POINT);
dxstate.texMinFilter.set(D3DTEXF_POINT);
}
dxstate.texMipLodBias.set(0.0f);
dxstate.texMaxMipLevel.set(0);
device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
HRESULT hr = device_->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coord, 5 * sizeof(float));
if (FAILED(hr)) {
Expand Down
29 changes: 21 additions & 8 deletions GPU/Directx9/TextureCacheDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,10 @@ static const u8 MinFilt[8] = {
};

static const u8 MipFilt[8] = {
D3DTEXF_POINT,
D3DTEXF_LINEAR,
D3DTEXF_POINT,
D3DTEXF_LINEAR,
D3DTEXF_NONE,
D3DTEXF_NONE,
D3DTEXF_NONE,
D3DTEXF_NONE,
D3DTEXF_POINT, // GL_NEAREST_MIPMAP_NEAREST,
D3DTEXF_POINT, // GL_LINEAR_MIPMAP_NEAREST,
D3DTEXF_LINEAR, // GL_NEAREST_MIPMAP_LINEAR,
Expand All @@ -160,17 +160,26 @@ void TextureCacheDX9::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
GETexLevelMode mode = gstate.getTexLevelMode();
switch (mode) {
case GE_TEXLEVEL_MODE_AUTO:
// TODO
dxstate.texMaxMipLevel.set(0);
dxstate.texMipLodBias.set(lodBias);
break;
case GE_TEXLEVEL_MODE_CONST:
dxstate.texMipLodBias.set(lodBias);
// TODO
// TODO: This is just an approximation - texMaxMipLevel sets the lowest numbered mip to use.
// Unfortunately, this doesn't support a const 1.5 or etc.
dxstate.texMaxMipLevel.set((int)lodBias);
dxstate.texMipLodBias.set(-1000.0f);
break;
case GE_TEXLEVEL_MODE_SLOPE:
// TODO
WARN_LOG_REPORT_ONCE(texSlope, G3D, "Unsupported texture lod slope: %f + %f", gstate.getTextureLodSlope(), lodBias);
// TODO: This behavior isn't correct.
dxstate.texMaxMipLevel.set(0);
dxstate.texMipLodBias.set(lodBias);
break;
}
entry.lodBias = lodBias;
} else {
dxstate.texMaxMipLevel.set(0);
dxstate.texMipLodBias.set(0.0f);
}

D3DTEXTUREFILTERTYPE minf = (D3DTEXTUREFILTERTYPE)MinFilt[minFilt];
Expand Down Expand Up @@ -199,6 +208,8 @@ void TextureCacheDX9::SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHe
dxstate.texMinFilter.set(MinFilt[minFilt]);
dxstate.texMipFilter.set(MipFilt[minFilt]);
dxstate.texMagFilter.set(MagFilt[magFilt]);
dxstate.texMipLodBias.set(0.0f);
dxstate.texMaxMipLevel.set(0.0f);

// Often the framebuffer will not match the texture size. We'll wrap/clamp in the shader in that case.
// This happens whether we have OES_texture_npot or not.
Expand Down Expand Up @@ -437,6 +448,8 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame
device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
device_->SetSamplerState(0, D3DSAMP_MIPMAPLODBIAS, 0);
device_->SetSamplerState(0, D3DSAMP_MAXMIPLEVEL, 0);

shaderApply.Shade();

Expand Down
23 changes: 17 additions & 6 deletions GPU/GLES/TextureCacheGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,21 +136,33 @@ void TextureCacheGLES::UpdateSamplingParams(TexCacheEntry &entry, bool force) {
GETexLevelMode mode = gstate.getTexLevelMode();
switch (mode) {
case GE_TEXLEVEL_MODE_AUTO:
// TODO
break;
case GE_TEXLEVEL_MODE_CONST:
// Sigh, LOD_BIAS is not even in ES 3.0..
#ifndef USING_GLES2
// Sigh, LOD_BIAS is not even in ES 3.0.. but we could do it in the shader via texture()...
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias);
#endif
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)entry.maxLevel);
break;
case GE_TEXLEVEL_MODE_CONST:
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, lodBias);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, lodBias);
break;
case GE_TEXLEVEL_MODE_SLOPE:
// TODO
WARN_LOG_REPORT_ONCE(texSlope, G3D, "Unsupported texture lod slope: %f + %f", gstate.getTextureLodSlope(), lodBias);
// TODO: This behavior isn't correct.
#ifndef USING_GLES2
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, lodBias);
#endif
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)entry.maxLevel);
break;
}
}
entry.lodBias = lodBias;
}
} else if (gstate_c.Supports(GPU_SUPPORTS_TEXTURE_LOD_CONTROL)) {
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, 0.0f);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 0.0f);
}

if (force || entry.minFilt != minFilt) {
Expand Down Expand Up @@ -699,7 +711,6 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImag
LoadTextureLevel(*entry, replaced, i, replaceImages, scaleFactor, dstFmt);
}
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, maxLevel);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, (float)maxLevel);
}
} else {
// Avoid PowerVR driver bug
Expand Down
1 change: 1 addition & 0 deletions GPU/GPUState.h
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ struct GPUgstate {
bool isTextureSwizzled() const { return texmode & 1; }
bool isClutSharedForMipmaps() const { return (texmode & 0x100) == 0; }
int getTextureMaxLevel() const { return (texmode >> 16) & 0x7; }
float getTextureLodSlope() const { return getFloat24(texlodslope); }

// Lighting
bool isLightingEnabled() const { return lightingEnable & 1; }
Expand Down
4 changes: 2 additions & 2 deletions GPU/Vulkan/FramebufferVulkan.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ class FramebufferManagerVulkan : public FramebufferManagerCommon {
// The command buffer of the current framebuffer pass being rendered to.
// One framebuffer can be used as a texturing source at multiple times in a frame,
// but then the contents have to be copied out into a new texture every time.
VkCommandBuffer curCmd_;
VkCommandBuffer cmdInit_;
VkCommandBuffer curCmd_ = VK_NULL_HANDLE;
VkCommandBuffer cmdInit_ = VK_NULL_HANDLE;

// Used by DrawPixels
VulkanTexture *drawPixelsTex_;
Expand Down
3 changes: 2 additions & 1 deletion ext/native/gfx/d3d9_state.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ void DirectXState::Restore() {
texMagFilter.restore(); count++;
texMipFilter.restore(); count++;
texMipLodBias.restore(); count++;
texMaxMipLevel.restore(); count++;
texAddressU.restore(); count++;
texAddressV.restore(); count++;
}
Expand All @@ -76,4 +77,4 @@ void DirectXState::SetVSyncInterval(int interval) {

} // namespace DX9

#endif // _MSC_VER
#endif // _MSC_VER
1 change: 1 addition & 0 deletions ext/native/gfx/d3d9_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ class DirectXState {
DxSampler0State1<D3DSAMP_MAGFILTER, D3DTEXF_POINT> texMagFilter;
DxSampler0State1<D3DSAMP_MIPFILTER, D3DTEXF_NONE> texMipFilter;
DxSampler0State1Float<D3DSAMP_MIPMAPLODBIAS, 0> texMipLodBias;
DxSampler0State1<D3DSAMP_MAXMIPLEVEL, 0> texMaxMipLevel;
DxSampler0State1<D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP> texAddressU;
DxSampler0State1<D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP> texAddressV;

Expand Down
9 changes: 8 additions & 1 deletion headless/Headless.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ int printUsage(const char *progname, const char *reason)
#if defined(HEADLESSHOST_CLASS)
{
fprintf(stderr, " --graphics=BACKEND use the full gpu backend (slower)\n");
fprintf(stderr, " options: gles, software, directx9\n");
fprintf(stderr, " options: gles, software, directx9, etc.\n");
fprintf(stderr, " --screenshot=FILE compare against a screenshot\n");
}
#endif
Expand Down Expand Up @@ -157,6 +157,8 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool
static double deadline;
deadline = time_now() + timeout;

PSP_BeginHostFrame();

coreState = CORE_RUNNING;
while (coreState == CORE_RUNNING)
{
Expand All @@ -180,6 +182,8 @@ bool RunAutoTest(HeadlessHost *headlessHost, CoreParameter &coreParameter, bool
}
}

PSP_EndHostFrame();

PSP_Shutdown();

headlessHost->FlushDebugOutput();
Expand Down Expand Up @@ -250,6 +254,8 @@ int main(int argc, const char* argv[])
gpuCore = GPUCORE_SOFTWARE;
else if (!strcasecmp(gpuName, "directx9"))
gpuCore = GPUCORE_DIRECTX9;
else if (!strcasecmp(gpuName, "directx11"))
gpuCore = GPUCORE_DIRECTX11;
else if (!strcasecmp(gpuName, "vulkan"))
gpuCore = GPUCORE_VULKAN;
else if (!strcasecmp(gpuName, "null"))
Expand Down Expand Up @@ -356,6 +362,7 @@ int main(int argc, const char* argv[])
g_Config.bVertexDecoderJit = true;
g_Config.bBlockTransferGPU = true;
g_Config.iSplineBezierQuality = 2;
g_Config.bMipMap = true;

#ifdef _WIN32
InitSysDirectories();
Expand Down
9 changes: 5 additions & 4 deletions headless/Headless.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_ARCH_32=1;_CONSOLE;_UNICODE;UNICODE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../dx9sdk/Include/DX11;../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<BasicRuntimeChecks>Default</BasicRuntimeChecks>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
Expand Down Expand Up @@ -124,7 +124,7 @@
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_ARCH_64=1;_CONSOLE;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../dx9sdk/Include/DX11;../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
<OmitFramePointers>false</OmitFramePointers>
Expand Down Expand Up @@ -159,7 +159,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_ARCH_32=1;_CONSOLE;_UNICODE;UNICODE;%(PreprocessorDefinitions);_CRT_SECURE_NO_WARNINGS</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../dx9sdk/Include/DX11;../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
Expand Down Expand Up @@ -194,7 +194,7 @@
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>USING_WIN_UI;GLEW_STATIC;_CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_ARCH_64=1;_CONSOLE;_UNICODE;UNICODE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>../dx9sdk/Include/DX11;../Common;..;../Core;../ext/glew;../ext/native</AdditionalIncludeDirectories>
<BufferSecurityCheck>false</BufferSecurityCheck>
<EnableEnhancedInstructionSet>NotSet</EnableEnhancedInstructionSet>
<FloatingPointModel>Fast</FloatingPointModel>
Expand Down Expand Up @@ -225,6 +225,7 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\ext\glew\glew.c" />
<ClCompile Include="..\Windows\GPU\D3D11Context.cpp" />
<ClCompile Include="..\Windows\GPU\D3D9Context.cpp" />
<ClCompile Include="..\Windows\GPU\WindowsGLContext.cpp" />
<ClCompile Include="..\Windows\GPU\WindowsVulkanContext.cpp" />
Expand Down
3 changes: 3 additions & 0 deletions headless/Headless.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<ClCompile Include="..\Windows\W32Util\Misc.cpp">
<Filter>Windows</Filter>
</ClCompile>
<ClCompile Include="..\Windows\GPU\D3D11Context.cpp">
<Filter>Windows</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="headless.txt" />
Expand Down
4 changes: 3 additions & 1 deletion headless/WindowsHeadlessHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "GPU/GPUState.h"
#include "Windows/GPU/WindowsGLContext.h"
#include "Windows/GPU/D3D9Context.h"
#include "Windows/GPU/D3D11Context.h"
#include "Windows/GPU/WindowsVulkanContext.h"

#include "base/logging.h"
Expand Down Expand Up @@ -164,7 +165,8 @@ bool WindowsHeadlessHost::InitGraphics(std::string *error_message, GraphicsConte
break;

case GPUCORE_DIRECTX11:
return false;
graphicsContext = new D3D11Context();
break;

case GPUCORE_VULKAN:
graphicsContext = new WindowsVulkanContext();
Expand Down