Kill off the GL state cache

This commit is contained in:
Henrik Rydgård 2017-12-12 15:04:46 +01:00
parent f3282dcfda
commit 51f467a7b3
22 changed files with 110 additions and 437 deletions

View file

@ -887,8 +887,6 @@ add_library(native STATIC
ext/native/file/vfs.h
ext/native/file/zip_read.cpp
ext/native/file/zip_read.h
ext/native/gfx/GLStateCache.cpp
ext/native/gfx/GLStateCache.h
ext/native/gfx/gl_common.h
ext/native/gfx/gl_debug_log.cpp
ext/native/gfx/gl_debug_log.h

View file

@ -23,7 +23,6 @@
#include "Core/Reporting.h"
#include "DepalettizeShaderGLES.h"
#include "GPU/GLES/TextureCacheGLES.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/Common/DepalettizeShaderCommon.h"
#ifdef _WIN32

View file

@ -83,7 +83,6 @@
#include "GPU/Common/SplineCommon.h"
#include "GPU/Common/VertexDecoderCommon.h"
#include "GPU/Common/SoftwareTransformCommon.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/GLES/FragmentTestCacheGLES.h"
#include "GPU/GLES/StateMappingGLES.h"
#include "GPU/GLES/TextureCacheGLES.h"
@ -585,7 +584,7 @@ rotateVBO:
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
}
ApplyDrawStateLate();
ApplyDrawStateLate(false, 0);
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);
GLRInputLayout *inputLayout = SetupDecFmtForDraw(program, dec_->GetDecVtxFmt());
@ -646,14 +645,11 @@ rotateVBO:
prim, vertexCount,
dec_->VertexType(), inds, GE_VTYPE_IDX_16BIT, dec_->GetDecVtxFmt(),
maxIndex, drawBuffer, numTrans, drawIndexed, &params, &result);
ApplyDrawStateLate();
ApplyDrawStateLate(result.setStencil, result.stencilValue);
LinkedShader *program = shaderManager_->ApplyFragmentShader(vsid, vshader, lastVType_, prim);
if (result.action == SW_DRAW_PRIMITIVES) {
if (result.setStencil) {
glstate.stencilFunc.set(GL_ALWAYS, result.stencilValue, 255);
}
const int vertexSize = sizeof(transformed[0]);
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;

View file

@ -165,7 +165,7 @@ private:
void DoFlush();
void ApplyDrawState(int prim);
void ApplyDrawStateLate();
void ApplyDrawStateLate(bool setStencil, int stencilValue);
void ResetShaderBlending();
GLRInputLayout *SetupDecFmtForDraw(LinkedShader *program, const DecVtxFormat &decFmt);

View file

@ -19,7 +19,6 @@
#include <map>
#include "Common/CommonTypes.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/GLES/TextureCacheGLES.h"
#include "GPU/ge_constants.h"

View file

@ -1058,6 +1058,7 @@ void FramebufferManagerGLES::DestroyAllFBOs() {
void FramebufferManagerGLES::Resized() {
FramebufferManagerCommon::Resized();
render_->Resize(PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
if (UpdateSize()) {
DestroyAllFBOs();
}

View file

@ -36,7 +36,6 @@
#include "GPU/GeDisasm.h"
#include "GPU/Common/FramebufferCommon.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/GLES/ShaderManagerGLES.h"
#include "GPU/GLES/GPU_GLES.h"
#include "GPU/GLES/FramebufferManagerGLES.h"
@ -160,9 +159,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
// Update again after init to be sure of any silly driver problems.
UpdateVsyncInterval(true);
// Some of our defaults are different from hw defaults, let's assert them.
// We restore each frame anyway, but here is convenient for tests.
glstate.Restore();
textureCacheGL_->NotifyConfigChanged();
// Load shader cache.
@ -431,14 +427,6 @@ void GPU_GLES::Reinitialize() {
}
void GPU_GLES::InitClear() {
bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE;
if (useNonBufferedRendering) {
glstate.depthWrite.set(GL_TRUE);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glClearColor(0,0,0,1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight);
}
void GPU_GLES::BeginHostFrame() {
@ -497,7 +485,6 @@ void GPU_GLES::UpdateCmdInfo() {
}
void GPU_GLES::ReapplyGfxState() {
glstate.Restore();
GPUCommon::ReapplyGfxState();
}
@ -557,9 +544,6 @@ void GPU_GLES::CopyDisplayToOutput() {
shaderManagerGL_->DirtyLastShader();
glstate.depthWrite.set(GL_TRUE);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
framebufferManagerGL_->CopyDisplayToOutput();
framebufferManagerGL_->EndFrame();
@ -768,8 +752,6 @@ void GPU_GLES::ClearShaderCache() {
void GPU_GLES::CleanupBeforeUI() {
// Clear any enabled vertex arrays.
shaderManagerGL_->DirtyLastShader();
glstate.arrayBuffer.bind(0);
glstate.elementArrayBuffer.bind(0);
}
void GPU_GLES::DoState(PointerWrap &p) {

View file

@ -26,6 +26,7 @@
#include "base/logging.h"
#include "base/timeutil.h"
#include "gfx/gl_debug_log.h"
#include "gfx_es2/gpu_features.h"
#include "thin3d/GLRenderManager.h"
#include "i18n/i18n.h"
#include "math/math_util.h"
@ -39,7 +40,6 @@
#include "GPU/Math3D.h"
#include "GPU/GPUState.h"
#include "GPU/ge_constants.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/GLES/ShaderManagerGLES.h"
#include "GPU/GLES/DrawEngineGLES.h"
#include "FramebufferManagerGLES.h"

View file

@ -32,7 +32,6 @@
#include "Core/Config.h"
#include "Core/Reporting.h"
#include "GPU/GLES/GPU_GLES.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/GLES/ShaderManagerGLES.h"
#include "GPU/GLES/TextureCacheGLES.h"
#include "GPU/GLES/FramebufferManagerGLES.h"
@ -169,12 +168,6 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
bool colorMask = gstate.isClearModeColorMask();
bool alphaMask = gstate.isClearModeAlphaMask();
renderManager->SetNoBlendAndMask((colorMask ? 7 : 0) | (alphaMask ? 8 : 0));
#ifndef USING_GLES2
if (gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) {
// Logic Ops
glstate.colorLogicOp.disable();
}
#endif
} else {
// Do the large chunks of state conversion. We might be able to hide these two behind a dirty-flag each,
// to avoid recomputing heavy stuff unnecessarily every draw call.
@ -280,7 +273,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
if (gstate.isClearModeDepthMask()) {
framebufferManager_->SetDepthUpdated();
}
renderManager->SetStencil(gstate.isClearModeAlphaMask() && enableStencilTest, GL_ALWAYS, GL_REPLACE, GL_REPLACE, GL_REPLACE, 0xFF, 0xFF, 0xFF);
renderManager->SetStencilFunc(gstate.isClearModeAlphaMask() && enableStencilTest, GL_ALWAYS, 0xFF, 0xFF);
renderManager->SetStencilOp(0xFF, GL_REPLACE, GL_REPLACE, GL_REPLACE);
renderManager->SetDepth(true, gstate.isClearModeDepthMask() ? true : false, GL_ALWAYS);
} else {
// Depth Test
@ -293,9 +287,8 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
ConvertStencilFuncState(stencilState);
// Stencil Test
if (stencilState.enabled) {
renderManager->SetStencil(stencilState.enabled, compareOps[stencilState.testFunc],
stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass],
stencilState.writeMask, stencilState.testMask, stencilState.testRef);
renderManager->SetStencilFunc(stencilState.enabled, compareOps[stencilState.testFunc], stencilState.testRef, stencilState.testMask);
renderManager->SetStencilOp(stencilState.writeMask, stencilOps[stencilState.sFail], stencilOps[stencilState.zFail], stencilOps[stencilState.zPass]);
} else {
renderManager->SetStencilDisabled();
}
@ -332,7 +325,11 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
}
}
void DrawEngineGLES::ApplyDrawStateLate() {
void DrawEngineGLES::ApplyDrawStateLate(bool setStencil, int stencilValue) {
if (setStencil) {
render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, stencilValue, 255);
}
// At this point, we know if the vertices are full alpha or not.
// TODO: Set the nearest/linear here (since we correctly know if alpha/color tests are needed)?
if (!gstate.isModeClear()) {

View file

@ -17,7 +17,6 @@
#include "gfx_es2/glsl_program.h"
#include "Core/Reporting.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/Common/StencilCommon.h"
#include "GPU/GLES/FramebufferManagerGLES.h"
#include "GPU/GLES/ShaderManagerGLES.h"
@ -111,12 +110,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
}
// Let's not bother with the shader if it's just zero.
glstate.scissorTest.disable();
glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glClearColor(0, 0, 0, 0);
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
return true;
}
@ -150,8 +144,6 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
DisableState();
render_->SetNoBlendAndMask(0x8);
glstate.stencilTest.enable();
glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE);
bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT);
@ -178,7 +170,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
textureCacheGL_->ForgetLastTexture();
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT);
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF);
render_->SetStencilFunc(GL_TRUE, GL_ALWAYS, 0xFF, 0xFF);
for (int i = 1; i < values; i += i) {
if (!(usedBits & i)) {
@ -186,18 +178,17 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
continue;
}
if (dstBuffer->format == GE_FORMAT_4444) {
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, (i << 4) | i, 0xFF, 0xFF);
render_->SetStencilOp((i << 4) | i, GL_KEEP, GL_KEEP, GL_KEEP);
render_->SetUniformF1(&u_stencilValue, i * (16.0f / 255.0f));
} else if (dstBuffer->format == GE_FORMAT_5551) {
glstate.stencilMask.set(0xFF);
render_->SetStencilOp(0xFF, GL_KEEP, GL_KEEP, GL_KEEP);
render_->SetUniformF1(&u_stencilValue, i * (128.0f / 255.0f));
} else {
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, i, 0xFF, 0xFF);
render_->SetStencilOp(i, GL_KEEP, GL_KEEP, GL_KEEP);
render_->SetUniformF1(&u_stencilValue, i * (1.0f / 255.0f));
}
DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, u1, v1, ROTATION_LOCKED_HORIZONTAL, DRAWTEX_NEAREST);
}
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF);
if (useBlit) {
draw_->BlitFramebuffer(blitFBO, 0, 0, w, h, dstBuffer->fbo, 0, 0, dstBuffer->renderWidth, dstBuffer->renderHeight, Draw::FB_STENCIL_BIT, Draw::FB_BLIT_NEAREST);

View file

@ -32,7 +32,6 @@
#include "Core/Reporting.h"
#include "GPU/ge_constants.h"
#include "GPU/GPUState.h"
#include "ext/native/gfx/GLStateCache.h"
#include "GPU/GLES/TextureCacheGLES.h"
#include "GPU/GLES/FramebufferManagerGLES.h"
#include "GPU/GLES/FragmentShaderGeneratorGLES.h"
@ -523,6 +522,10 @@ GLenum ToGLESFormat(ReplacedTextureFormat fmt) {
void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry, bool replaceImages) {
entry->status &= ~TexCacheEntry::STATUS_ALPHA_MASK;
// Never replace images in-place - there's no such thing, drivers have to fake it anyway, at least if
// the image has been in use within the last frame or two.
replaceImages = false;
// For the estimate, we assume cluts always point to 8888 for simplicity.
cacheSizeEstimate_ += EstimateTexMemoryUsage(entry);

View file

@ -1,5 +1,4 @@
#include "debugger_memorytex.h"
#include "gfx/GLStateCache.h"
#include "gfx/gl_common.h"
#include "ui_debugger_memorytex.h"
#include "Core/MemMap.h"

View file

@ -75,7 +75,6 @@ LOCAL_SRC_FILES :=\
gfx_es2/draw_buffer.cpp.arm \
gfx_es2/draw_text.cpp.arm \
gfx_es2/draw_text_android.cpp.arm \
gfx/GLStateCache.cpp.arm \
gfx/gl_debug_log.cpp \
gfx/texture_atlas.cpp \
image/zim_load.cpp \

View file

@ -1,52 +0,0 @@
#include <stdlib.h>
#include "base/logging.h"
#include "gfx/GLStateCache.h"
OpenGLState glstate;
int OpenGLState::state_count = 0;
void OpenGLState::Restore() {
int count = 0;
blend.restore(); count++;
blendEquationSeparate.restore(); count++;
blendFuncSeparate.restore(); count++;
blendColor.restore(); count++;
scissorTest.restore(); count++;
scissorRect.restore(); count++;
cullFace.restore(); count++;
cullFaceMode.restore(); count++;
frontFace.restore(); count++;
depthTest.restore(); count++;
depthRange.restore(); count++;
depthFunc.restore(); count++;
depthWrite.restore(); count++;
colorMask.restore(); count++;
viewport.restore(); count++;
stencilTest.restore(); count++;
stencilOp.restore(); count++;
stencilFunc.restore(); count++;
stencilMask.restore(); count++;
dither.restore(); count++;
#if !defined(USING_GLES2)
colorLogicOp.restore(); count++;
logicOp.restore(); count++;
#endif
arrayBuffer.restore(); count++;
elementArrayBuffer.restore(); count++;
if (count != state_count) {
FLOG("OpenGLState::Restore is missing some states");
}
}

View file

@ -1,283 +0,0 @@
#pragma once
#include <functional>
#include <cstring> // for memcmp
#include "gfx/gl_common.h"
#include "gfx_es2/gpu_features.h"
// OpenGL state cache.
// Probably only really worth it in rendering cores on weak mobile hardware.
class OpenGLState {
private:
template<GLenum cap, bool init>
class BoolState {
private:
bool v;
public:
BoolState() : v(init) {
OpenGLState::state_count++;
}
inline void set(bool value) {
if (value != v) {
v = value;
restore();
}
}
inline void force(bool value) {
bool old = v;
set(value);
v = old;
}
inline void enable() {
set(true);
}
inline void disable() {
set(false);
}
operator bool() const {
return isset();
}
inline bool isset() {
return v;
}
void restore() {
if (v)
glEnable(cap);
else
glDisable(cap);
}
};
#define STATE1(func, p1type, p1def) \
class SavedState1_##func { \
p1type p1; \
public: \
SavedState1_##func() : p1(p1def) { \
OpenGLState::state_count++; \
} \
void set(p1type newp1) { \
if (newp1 != p1) { \
p1 = newp1; \
restore(); \
} \
} \
void force(p1type newp1) { \
p1type old = p1; \
set(newp1); \
p1 = old; \
} \
inline void restore() { \
func(p1); \
} \
}
#define STATE2(func, p1type, p2type, p1def, p2def) \
class SavedState2_##func { \
p1type p1; \
p2type p2; \
public: \
SavedState2_##func() : p1(p1def), p2(p2def) { \
OpenGLState::state_count++; \
} \
inline void set(p1type newp1, p2type newp2) { \
if (newp1 != p1 || newp2 != p2) { \
p1 = newp1; \
p2 = newp2; \
restore(); \
} \
} \
void force(p1type newp1, p2type newp2) { \
p1type old1 = p1; \
p2type old2 = p2; \
set(newp1, newp2); \
p1 = old1; \
p2 = old2; \
} \
inline void restore() { \
func(p1, p2); \
} \
}
#define STATE3(func, p1type, p2type, p3type, p1def, p2def, p3def) \
class SavedState3_##func { \
p1type p1; \
p2type p2; \
p3type p3; \
public: \
SavedState3_##func() : p1(p1def), p2(p2def), p3(p3def) { \
OpenGLState::state_count++; \
} \
inline void set(p1type newp1, p2type newp2, p3type newp3) { \
if (newp1 != p1 || newp2 != p2 || newp3 != p3) { \
p1 = newp1; \
p2 = newp2; \
p3 = newp3; \
restore(); \
} \
} \
void force(p1type newp1, p2type newp2, p3type newp3) { \
p1type old1 = p1; \
p2type old2 = p2; \
p3type old3 = p3; \
set(newp1, newp2, newp3); \
p1 = old1; \
p2 = old2; \
p3 = old3; \
} \
inline void restore() { \
func(p1, p2, p3); \
} \
}
#define STATE4(func, p1type, p2type, p3type, p4type, p1def, p2def, p3def, p4def) \
class SavedState4_##func { \
p1type p1; \
p2type p2; \
p3type p3; \
p4type p4; \
public: \
SavedState4_##func() : p1(p1def), p2(p2def), p3(p3def), p4(p4def) { \
OpenGLState::state_count++; \
} \
inline void set(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \
if (newp1 != p1 || newp2 != p2 || newp3 != p3 || newp4 != p4) { \
p1 = newp1; \
p2 = newp2; \
p3 = newp3; \
p4 = newp4; \
restore(); \
} \
} \
void force(p1type newp1, p2type newp2, p3type newp3, p4type newp4) { \
p1type old1 = p1; \
p2type old2 = p2; \
p3type old3 = p3; \
p4type old4 = p4; \
set(newp1, newp2, newp3, newp4); \
p1 = old1; \
p2 = old2; \
p3 = old3; \
p4 = old4; \
} \
inline void restore() { \
func(p1, p2, p3, p4); \
} \
}
#define STATEFLOAT4(func, def) \
class SavedState4_##func { \
float p[4]; \
public: \
SavedState4_##func() { \
for (int i = 0; i < 4; i++) {p[i] = def;} \
OpenGLState::state_count++; \
} \
inline void set(const float v[4]) { \
if (memcmp(p, v, sizeof(float) * 4)) { \
memcpy(p, v, sizeof(float) * 4); \
restore(); \
} \
} \
void force(const float v[4]) { \
float old[4]; \
memcpy(old, p, sizeof(float) * 4); \
set(v); \
memcpy(p, old, sizeof(float) * 4); \
} \
inline void restore() { \
func(p[0], p[1], p[2], p[3]); \
} \
}
#define STATEBIND(func, target) \
class SavedBind_##func_##target { \
GLuint val_; \
public: \
SavedBind_##func_##target() { \
val_ = 0; \
OpenGLState::state_count++; \
} \
inline void bind(GLuint val) { \
if (val_ != val) { \
val_ = val; \
restore(); \
} \
} \
inline void force(GLuint val) { \
GLuint old = val_; \
bind(val); \
val_ = old; \
} \
inline void unbind() { \
bind(0); \
} \
inline void restore() { \
func(target, val_); \
} \
}
public:
static int state_count;
OpenGLState() {}
void Restore();
// When adding a state here, don't forget to add it to OpenGLState::Restore() too
// Blending
BoolState<GL_BLEND, false> blend;
STATE4(glBlendFuncSeparate, GLenum, GLenum, GLenum, GLenum, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) blendFuncSeparate;
// On OpenGL ES, using minmax blend requires glBlendEquationEXT (in theory at least but I don't think it's true in practice)
STATE2(glBlendEquationSeparate, GLenum, GLenum, GL_FUNC_ADD, GL_FUNC_ADD) blendEquationSeparate;
STATEFLOAT4(glBlendColor, 1.0f) blendColor;
// Logic Ops. Not available on OpenGL ES at all.
#if !defined(USING_GLES2)
BoolState<GL_COLOR_LOGIC_OP, false> colorLogicOp;
STATE1(glLogicOp, GLenum, GL_COPY) logicOp;
#endif
// Dither
BoolState<GL_DITHER, false> dither;
// Cull Face
BoolState<GL_CULL_FACE, false> cullFace;
STATE1(glCullFace, GLenum, GL_FRONT) cullFaceMode;
STATE1(glFrontFace, GLenum, GL_CCW) frontFace;
// Depth Test
BoolState<GL_DEPTH_TEST, false> depthTest;
#if defined(USING_GLES2)
STATE2(glDepthRangef, float, float, 0.f, 1.f) depthRange;
#else
STATE2(glDepthRange, double, double, 0.0, 1.0) depthRange;
#endif
STATE1(glDepthFunc, GLenum, GL_LESS) depthFunc;
STATE1(glDepthMask, GLboolean, GL_TRUE) depthWrite;
// Color Mask
STATE4(glColorMask, bool, bool, bool, bool, true, true, true, true) colorMask;
// Viewport
STATE4(glViewport, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) viewport;
// Scissor Test
BoolState<GL_SCISSOR_TEST, false> scissorTest;
STATE4(glScissor, GLint, GLint, GLsizei, GLsizei, 0, 0, 128, 128) scissorRect;
// Stencil Test
BoolState<GL_STENCIL_TEST, false> stencilTest;
STATE3(glStencilOp, GLenum, GLenum, GLenum, GL_KEEP, GL_KEEP, GL_KEEP) stencilOp;
STATE3(glStencilFunc, GLenum, GLint, GLuint, GL_ALWAYS, 0, 0xFF) stencilFunc;
STATE1(glStencilMask, GLuint, 0xFF) stencilMask;
STATEBIND(glBindBuffer, GL_ARRAY_BUFFER) arrayBuffer;
STATEBIND(glBindBuffer, GL_ELEMENT_ARRAY_BUFFER) elementArrayBuffer;
};
#undef STATE1
#undef STATE2
extern OpenGLState glstate;

View file

@ -232,7 +232,6 @@
<ClInclude Include="file\free.h" />
<ClInclude Include="gfx\d3d9_shader.h" />
<ClInclude Include="gfx\d3d9_state.h" />
<ClInclude Include="gfx\GLStateCache.h" />
<ClInclude Include="gfx\gl_common.h" />
<ClInclude Include="gfx\gl_debug_log.h" />
<ClInclude Include="gfx\texture_atlas.h" />
@ -693,7 +692,6 @@
<ClCompile Include="file\free.cpp" />
<ClCompile Include="gfx\d3d9_shader.cpp" />
<ClCompile Include="gfx\d3d9_state.cpp" />
<ClCompile Include="gfx\GLStateCache.cpp" />
<ClCompile Include="gfx\gl_debug_log.cpp" />
<ClCompile Include="gfx\texture_atlas.cpp" />
<ClCompile Include="gfx_es2\draw_text_android.cpp" />

View file

@ -302,9 +302,6 @@
<ClInclude Include="gfx\d3d9_state.h">
<Filter>gfx</Filter>
</ClInclude>
<ClInclude Include="gfx\GLStateCache.h">
<Filter>gfx</Filter>
</ClInclude>
<ClInclude Include="thin3d\d3d11_loader.h">
<Filter>thin3d</Filter>
</ClInclude>
@ -775,9 +772,6 @@
<ClCompile Include="gfx\d3d9_state.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="gfx\GLStateCache.cpp">
<Filter>gfx</Filter>
</ClCompile>
<ClCompile Include="thin3d\d3d11_loader.cpp">
<Filter>thin3d</Filter>
</ClCompile>
@ -883,4 +877,4 @@
<UniqueIdentifier>{06c6305a-a646-485b-85b9-645a24dd6553}</UniqueIdentifier>
</Filter>
</ItemGroup>
</Project>
</Project>

View file

@ -279,13 +279,24 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
glBlendColor(c.blendColor.color[0], c.blendColor.color[1], c.blendColor.color[2], c.blendColor.color[3]);
break;
case GLRRenderCommand::VIEWPORT:
{
float y = c.viewport.vp.y;
if (!curFramebuffer_)
y = curFBHeight_ - y - c.viewport.vp.h;
// TODO: Support FP viewports through glViewportArrays
glViewport((GLint)c.viewport.vp.x, (GLint)c.viewport.vp.y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h);
glViewport((GLint)c.viewport.vp.x, (GLint)y, (GLsizei)c.viewport.vp.w, (GLsizei)c.viewport.vp.h);
glDepthRange(c.viewport.vp.minZ, c.viewport.vp.maxZ);
break;
}
case GLRRenderCommand::SCISSOR:
glScissor(c.scissor.rc.x, c.scissor.rc.y, c.scissor.rc.w, c.scissor.rc.h);
{
int y = c.scissor.rc.y;
if (!curFramebuffer_)
y = curFBHeight_ - y - c.scissor.rc.h;
glScissor(c.scissor.rc.x, y, c.scissor.rc.w, c.scissor.rc.h);
break;
}
case GLRRenderCommand::UNIFORM4F:
{
int loc = c.uniform4.loc ? *c.uniform4.loc : -1;
@ -345,24 +356,30 @@ void GLQueueRunner::PerformRenderPass(const GLRStep &step) {
}
break;
}
case GLRRenderCommand::STENCIL:
if (c.stencil.enabled) {
case GLRRenderCommand::STENCILFUNC:
if (c.stencilFunc.enabled) {
glEnable(GL_STENCIL_TEST);
glStencilFunc(c.stencil.func, c.stencil.ref, c.stencil.compareMask);
glStencilOp(c.stencil.sFail, c.stencil.zFail, c.stencil.pass);
glStencilMask(c.stencil.writeMask);
} else {
glDisable(GL_STENCIL_TEST);
}
glStencilFunc(c.stencilFunc.func, c.stencilFunc.ref, c.stencilFunc.compareMask);
break;
case GLRRenderCommand::STENCILOP:
glStencilOp(c.stencilOp.sFail, c.stencilOp.zFail, c.stencilOp.pass);
glStencilMask(c.stencilOp.writeMask);
break;
case GLRRenderCommand::BINDTEXTURE:
{
GLint target = c.texture.slot;
if (target != activeTexture) {
glActiveTexture(GL_TEXTURE0 + target);
activeTexture = target;
GLint slot = c.texture.slot;
if (slot != activeTexture) {
glActiveTexture(GL_TEXTURE0 + slot);
activeTexture = slot;
}
if (c.texture.texture) {
glBindTexture(c.texture.texture->target, c.texture.texture->texture);
} else {
glBindTexture(GL_TEXTURE_2D, 0); // ?
}
glBindTexture(c.texture.texture->target, c.texture.texture->texture);
break;
}
case GLRRenderCommand::BINDPROGRAM:
@ -518,7 +535,13 @@ void GLQueueRunner::PerformReadbackImage(const GLRStep &pass) {
}
void GLQueueRunner::PerformBindFramebufferAsRenderTarget(const GLRStep &pass) {
if (pass.render.framebuffer) {
curFBWidth_ = pass.render.framebuffer->width;
curFBHeight_ = pass.render.framebuffer->height;
} else {
curFBWidth_ = targetWidth_;
curFBHeight_ = targetHeight_;
}
}
void GLQueueRunner::CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels) {

View file

@ -28,7 +28,8 @@ class GLRInputLayout;
enum class GLRRenderCommand : uint8_t {
DEPTH,
STENCIL,
STENCILFUNC,
STENCILOP,
BLEND,
BLENDCOLOR,
UNIFORM4I,
@ -77,13 +78,15 @@ struct GLRRenderData {
struct {
GLboolean enabled;
GLenum func;
uint8_t writeMask;
uint8_t compareMask;
uint8_t ref;
uint8_t compareMask;
} stencilFunc;
struct {
GLenum sFail;
GLenum zFail;
GLenum pass;
} stencil;
uint8_t writeMask;
} stencilOp; // also write mask
struct {
GLenum mode; // primitive
GLint buffer;
@ -299,6 +302,10 @@ public:
void CopyReadbackBuffer(int width, int height, Draw::DataFormat srcFormat, Draw::DataFormat destFormat, int pixelStride, uint8_t *pixels);
void Resize(int width, int height) {
targetWidth_ = width;
targetHeight_ = height;
}
private:
void PerformBindFramebufferAsRenderTarget(const GLRStep &pass);
void PerformRenderPass(const GLRStep &pass);
@ -318,8 +325,10 @@ private:
GLuint globalVAO_;
GLint curFramebuffer_ = 0;
int curFBWidth_;
int curFBHeight_;
int curFBWidth_ = 0;
int curFBHeight_ = 0;
int targetWidth_ = 0;
int targetHeight_ = 0;
// Readback buffer. Currently we only support synchronous readback, so we only really need one.
// We size it generously.

View file

@ -456,25 +456,31 @@ public:
curRenderStep_->commands.push_back(data);
}
void SetStencil(bool enabled, GLenum func, GLenum sFail, GLenum zFail, GLenum pass, uint8_t writeMask, uint8_t compareMask, uint8_t refValue) {
void SetStencilFunc(bool enabled, GLenum func, uint8_t refValue, uint8_t compareMask) {
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
GLRRenderData data{ GLRRenderCommand::STENCIL };
data.stencil.enabled = enabled;
data.stencil.func = func;
data.stencil.sFail = sFail;
data.stencil.zFail = zFail;
data.stencil.pass = pass;
data.stencil.writeMask = writeMask;
data.stencil.compareMask = compareMask;
data.stencil.ref = refValue;
GLRRenderData data{ GLRRenderCommand::STENCILFUNC };
data.stencilFunc.enabled = enabled;
data.stencilFunc.func = func;
data.stencilFunc.ref = refValue;
data.stencilFunc.compareMask = compareMask;
curRenderStep_->commands.push_back(data);
}
void SetStencilOp(uint8_t writeMask, GLenum sFail, GLenum zFail, GLenum pass) {
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
GLRRenderData data{ GLRRenderCommand::STENCILOP };
data.stencilOp.writeMask = writeMask;
data.stencilOp.sFail = sFail;
data.stencilOp.zFail = zFail;
data.stencilOp.pass = pass;
curRenderStep_->commands.push_back(data);
}
void SetStencilDisabled() {
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
GLRRenderData data;
data.cmd = GLRRenderCommand::STENCIL;
data.stencil.enabled = false;
data.cmd = GLRRenderCommand::STENCILFUNC;
data.stencilFunc.enabled = false;
curRenderStep_->commands.push_back(data);
}
@ -546,6 +552,12 @@ public:
return curFrame_;
}
void Resize(int width, int height) {
targetWidth_ = width;
targetHeight_ = height;
queueRunner_.Resize(width, height);
}
private:
void BeginSubmitFrame(int frame);
void EndSubmitFrame(int frame);
@ -601,6 +613,9 @@ private:
bool useThread_ = false;
int curFrame_ = 0;
int targetWidth_ = 0;
int targetHeight_ = 0;
};

View file

@ -633,7 +633,7 @@ public:
virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0;
// Necessary to correctly flip scissor rectangles etc for OpenGL.
void SetTargetSize(int w, int h) {
virtual void SetTargetSize(int w, int h) {
targetWidth_ = w;
targetHeight_ = h;
}

View file

@ -11,7 +11,6 @@
#include "thin3d/thin3d.h"
#include "gfx/gl_common.h"
#include "gfx/gl_debug_log.h"
#include "gfx/GLStateCache.h"
#include "gfx_es2/gpu_features.h"
#include "thin3d/GLRenderManager.h"
@ -207,7 +206,8 @@ public:
void Apply(GLRenderManager *render) {
render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp);
render->SetStencil(stencilEnabled, stencilCompareOp, stencilFail, stencilZFail, stencilPass, stencilWriteMask, stencilCompareMask, stencilReference);
render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilReference, stencilCompareMask);
render->SetStencilOp(stencilWriteMask, stencilFail, stencilZFail, stencilPass);
}
};
@ -345,6 +345,11 @@ public:
OpenGLContext();
virtual ~OpenGLContext();
void SetTargetSize(int w, int h) override {
DrawContext::SetTargetSize(w, h);
renderManager_.Resize(w, h);
}
const DeviceCaps &GetDeviceCaps() const override {
return caps_;
}