mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-01-31 02:23:51 +00:00
Minor cleanup in GL backend, fixes #13647
Was a stray old texture in boundTextures_ in thin3d. Now makes sure to invalidate them, and also make it possible to look up bound framebuffer textures when checking for valid tex parameters.
This commit is contained in:
parent
9f33a82b49
commit
5eea7435d0
@ -438,11 +438,6 @@ void GLQueueRunner::InitCreateFramebuffer(const GLRInitStep &step) {
|
||||
tex.wrapT = GL_CLAMP_TO_EDGE;
|
||||
tex.magFilter = linear ? GL_LINEAR : GL_NEAREST;
|
||||
tex.minFilter = linear ? GL_LINEAR : GL_NEAREST;
|
||||
if (gl_extensions.OES_texture_npot) {
|
||||
tex.canWrap = true;
|
||||
} else {
|
||||
tex.canWrap = isPowerOf2(fbo->width) && isPowerOf2(fbo->height);
|
||||
}
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex.wrapS);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex.wrapT);
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "Common/Log.h"
|
||||
#include "Common/MemoryUtil.h"
|
||||
#include "Common/Math/math_util.h"
|
||||
|
||||
#if 0 // def _DEBUG
|
||||
#define VLOG(...) INFO_LOG(G3D, __VA_ARGS__)
|
||||
@ -19,6 +20,23 @@ static bool OnRenderThread() {
|
||||
}
|
||||
#endif
|
||||
|
||||
GLRTexture::GLRTexture(int width, int height, int numMips) {
|
||||
if (gl_extensions.OES_texture_npot) {
|
||||
canWrap = true;
|
||||
} else {
|
||||
canWrap = isPowerOf2(width) && isPowerOf2(height);
|
||||
}
|
||||
w = width;
|
||||
h = height;
|
||||
this->numMips = numMips;
|
||||
}
|
||||
|
||||
GLRTexture::~GLRTexture() {
|
||||
if (texture) {
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
}
|
||||
|
||||
void GLDeleter::Take(GLDeleter &other) {
|
||||
_assert_msg_(IsEmpty(), "Deleter already has stuff");
|
||||
shaders = std::move(other.shaders);
|
||||
|
@ -23,13 +23,12 @@ class DrawContext;
|
||||
|
||||
class GLRTexture {
|
||||
public:
|
||||
~GLRTexture() {
|
||||
if (texture) {
|
||||
glDeleteTextures(1, &texture);
|
||||
}
|
||||
}
|
||||
GLRTexture(int width, int height, int numMips);
|
||||
~GLRTexture();
|
||||
|
||||
GLuint texture = 0;
|
||||
uint16_t w;
|
||||
uint16_t h;
|
||||
|
||||
// We don't trust OpenGL defaults - setting wildly off values ensures that we'll end up overwriting these parameters.
|
||||
GLenum target = 0xFFFF;
|
||||
@ -37,6 +36,7 @@ public:
|
||||
GLenum wrapT = 0xFFFF;
|
||||
GLenum magFilter = 0xFFFF;
|
||||
GLenum minFilter = 0xFFFF;
|
||||
uint8_t numMips = 0;
|
||||
bool canWrap = true;
|
||||
float anisotropy = -100000.0f;
|
||||
float minLod = -1000.0f;
|
||||
@ -47,7 +47,8 @@ public:
|
||||
class GLRFramebuffer {
|
||||
public:
|
||||
GLRFramebuffer(int _width, int _height, bool z_stencil)
|
||||
: width(_width), height(_height), z_stencil_(z_stencil) {
|
||||
: width(_width), height(_height), z_stencil_(z_stencil),
|
||||
color_texture(_width, _height, 1), z_stencil_texture(_width, _height, 1) {
|
||||
}
|
||||
|
||||
~GLRFramebuffer();
|
||||
@ -378,9 +379,11 @@ public:
|
||||
void WaitUntilQueueIdle();
|
||||
|
||||
// Creation commands. These were not needed in Vulkan since there we can do that on the main thread.
|
||||
GLRTexture *CreateTexture(GLenum target) {
|
||||
// We pass in width/height here even though it's not strictly needed until we support glTextureStorage
|
||||
// and then we'll also need formats and stuff.
|
||||
GLRTexture *CreateTexture(GLenum target, int width, int height, int numMips) {
|
||||
GLRInitStep step{ GLRInitStepType::CREATE_TEXTURE };
|
||||
step.create_texture.texture = new GLRTexture();
|
||||
step.create_texture.texture = new GLRTexture(width, height, numMips);
|
||||
step.create_texture.texture->target = target;
|
||||
initSteps_.push_back(step);
|
||||
return step.create_texture.texture;
|
||||
|
@ -386,7 +386,7 @@ public:
|
||||
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
|
||||
|
||||
void BindSamplerStates(int start, int count, SamplerState **states) override {
|
||||
if (start + count >= MAX_TEXTURE_SLOTS) {
|
||||
if (start + count > MAX_TEXTURE_SLOTS) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < count; i++) {
|
||||
@ -497,7 +497,9 @@ private:
|
||||
|
||||
// Bound state
|
||||
OpenGLSamplerState *boundSamplers_[MAX_TEXTURE_SLOTS]{};
|
||||
OpenGLTexture *boundTextures_[MAX_TEXTURE_SLOTS]{};
|
||||
// Point to GLRTexture directly because they can point to the textures
|
||||
// in framebuffers too (which also can be bound).
|
||||
const GLRTexture *boundTextures_[MAX_TEXTURE_SLOTS]{};
|
||||
|
||||
OpenGLPipeline *curPipeline_ = nullptr;
|
||||
OpenGLBuffer *curVBuffers_[4]{};
|
||||
@ -739,9 +741,7 @@ public:
|
||||
bool HasMips() const {
|
||||
return mipLevels_ > 1 || generatedMips_;
|
||||
}
|
||||
bool CanWrap() const {
|
||||
return canWrap_;
|
||||
}
|
||||
|
||||
TextureType GetType() const { return type_; }
|
||||
void Bind(int stage) {
|
||||
render_->BindTexture(stage, tex_);
|
||||
@ -749,6 +749,9 @@ public:
|
||||
int NumMipmaps() const {
|
||||
return mipLevels_;
|
||||
}
|
||||
const GLRTexture *GetTex() const {
|
||||
return tex_;
|
||||
}
|
||||
|
||||
private:
|
||||
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data, TextureCallback callback);
|
||||
@ -760,7 +763,6 @@ private:
|
||||
TextureType type_;
|
||||
int mipLevels_;
|
||||
bool generatedMips_;
|
||||
bool canWrap_;
|
||||
};
|
||||
|
||||
OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) : render_(render) {
|
||||
@ -771,9 +773,8 @@ OpenGLTexture::OpenGLTexture(GLRenderManager *render, const TextureDesc &desc) :
|
||||
format_ = desc.format;
|
||||
type_ = desc.type;
|
||||
GLenum target = TypeToTarget(desc.type);
|
||||
tex_ = render->CreateTexture(target);
|
||||
tex_ = render->CreateTexture(target, desc.width, desc.height, desc.mipLevels);
|
||||
|
||||
canWrap_ = isPowerOf2(width_) && isPowerOf2(height_);
|
||||
mipLevels_ = desc.mipLevels;
|
||||
if (desc.initData.empty())
|
||||
return;
|
||||
@ -1091,7 +1092,7 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
|
||||
}
|
||||
|
||||
void OpenGLContext::BindTextures(int start, int count, Texture **textures) {
|
||||
if (start + count >= MAX_TEXTURE_SLOTS) {
|
||||
if (start + count > MAX_TEXTURE_SLOTS) {
|
||||
return;
|
||||
}
|
||||
for (int i = start; i < start + count; i++) {
|
||||
@ -1102,14 +1103,14 @@ void OpenGLContext::BindTextures(int start, int count, Texture **textures) {
|
||||
continue;
|
||||
}
|
||||
glTex->Bind(i);
|
||||
boundTextures_[i] = glTex;
|
||||
boundTextures_[i] = glTex->GetTex();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLContext::ApplySamplers() {
|
||||
for (int i = 0; i < MAX_TEXTURE_SLOTS; i++) {
|
||||
const OpenGLSamplerState *samp = boundSamplers_[i];
|
||||
const OpenGLTexture *tex = boundTextures_[i];
|
||||
const GLRTexture *tex = boundTextures_[i];
|
||||
if (tex) {
|
||||
_assert_(samp);
|
||||
} else {
|
||||
@ -1117,7 +1118,7 @@ void OpenGLContext::ApplySamplers() {
|
||||
}
|
||||
GLenum wrapS;
|
||||
GLenum wrapT;
|
||||
if (tex->CanWrap()) {
|
||||
if (tex->canWrap) {
|
||||
wrapS = samp->wrapU;
|
||||
wrapT = samp->wrapV;
|
||||
} else {
|
||||
@ -1125,9 +1126,9 @@ void OpenGLContext::ApplySamplers() {
|
||||
wrapT = GL_CLAMP_TO_EDGE;
|
||||
}
|
||||
GLenum magFilt = samp->magFilt;
|
||||
GLenum minFilt = tex->HasMips() ? samp->mipMinFilt : samp->minFilt;
|
||||
GLenum minFilt = tex->numMips > 1 ? samp->mipMinFilt : samp->minFilt;
|
||||
renderManager_.SetTextureSampler(i, wrapS, wrapT, magFilt, minFilt, 0.0f);
|
||||
renderManager_.SetTextureLod(i, 0.0, (float)(tex->NumMipmaps() - 1), 0.0);
|
||||
renderManager_.SetTextureLod(i, 0.0, (float)(tex->numMips - 1), 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1376,12 +1377,18 @@ void OpenGLContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBCh
|
||||
OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo;
|
||||
|
||||
GLuint aspect = 0;
|
||||
if (channelBit & FB_COLOR_BIT)
|
||||
if (channelBit & FB_COLOR_BIT) {
|
||||
aspect |= GL_COLOR_BUFFER_BIT;
|
||||
if (channelBit & FB_DEPTH_BIT)
|
||||
boundTextures_[binding] = &fb->framebuffer_->color_texture;
|
||||
}
|
||||
if (channelBit & FB_DEPTH_BIT) {
|
||||
aspect |= GL_DEPTH_BUFFER_BIT;
|
||||
if (channelBit & FB_STENCIL_BIT)
|
||||
boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
|
||||
}
|
||||
if (channelBit & FB_STENCIL_BIT) {
|
||||
aspect |= GL_STENCIL_BUFFER_BIT;
|
||||
boundTextures_[binding] = &fb->framebuffer_->z_stencil_texture;
|
||||
}
|
||||
renderManager_.BindFramebufferAsTexture(fb->framebuffer_, binding, aspect, color);
|
||||
}
|
||||
|
||||
|
@ -605,6 +605,7 @@ void FramebufferManagerCommon::ReinterpretFramebufferFrom(VirtualFramebuffer *vf
|
||||
// Copy to a temp framebuffer.
|
||||
Draw::Framebuffer *temp = GetTempFBO(TempFBO::REINTERPRET, vfb->renderWidth, vfb->renderHeight);
|
||||
|
||||
draw_->InvalidateCachedState();
|
||||
draw_->CopyFramebufferImage(vfb->fbo, 0, 0, 0, 0, temp, 0, 0, 0, 0, vfb->renderWidth, vfb->renderHeight, 1, Draw::FBChannel::FB_COLOR_BIT, "reinterpret_prep");
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }, "reinterpret");
|
||||
draw_->BindPipeline(pipeline);
|
||||
|
@ -98,7 +98,7 @@ GLRTexture *DepalShaderCacheGLES::GetClutTexture(GEPaletteFormat clutFormat, con
|
||||
int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512;
|
||||
|
||||
DepalTexture *tex = new DepalTexture();
|
||||
tex->texture = render_->CreateTexture(GL_TEXTURE_2D);
|
||||
tex->texture = render_->CreateTexture(GL_TEXTURE_2D, texturePixels, 1, 1);
|
||||
|
||||
uint8_t *clutCopy = new uint8_t[1024];
|
||||
memcpy(clutCopy, rawClut, 1024);
|
||||
|
@ -696,7 +696,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p
|
||||
prevSizeU = size_u;
|
||||
prevSizeV = size_v;
|
||||
if (!data_tex[0])
|
||||
data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D);
|
||||
data_tex[0] = renderManager_->CreateTexture(GL_TEXTURE_2D, size_u * 3, size_v, 1);
|
||||
renderManager_->TextureImage(data_tex[0], 0, size_u * 3, size_v, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
renderManager_->FinalizeTexture(data_tex[0], 0, false);
|
||||
}
|
||||
@ -714,7 +714,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p
|
||||
if (prevSizeWU < weights.size_u) {
|
||||
prevSizeWU = weights.size_u;
|
||||
if (!data_tex[1])
|
||||
data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D);
|
||||
data_tex[1] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_u * 2, 1, 1);
|
||||
renderManager_->TextureImage(data_tex[1], 0, weights.size_u * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
renderManager_->FinalizeTexture(data_tex[1], 0, false);
|
||||
}
|
||||
@ -725,7 +725,7 @@ void TessellationDataTransferGLES::SendDataToShader(const SimpleVertex *const *p
|
||||
if (prevSizeWV < weights.size_v) {
|
||||
prevSizeWV = weights.size_v;
|
||||
if (!data_tex[2])
|
||||
data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D);
|
||||
data_tex[2] = renderManager_->CreateTexture(GL_TEXTURE_2D, weights.size_v * 2, 1, 1);
|
||||
renderManager_->TextureImage(data_tex[2], 0, weights.size_v * 2, 1, Draw::DataFormat::R32G32B32A32_FLOAT, nullptr, GLRAllocType::NONE, false);
|
||||
renderManager_->FinalizeTexture(data_tex[2], 0, false);
|
||||
}
|
||||
|
@ -144,7 +144,7 @@ GLRTexture *FragmentTestCacheGLES::CreateTestTexture(const GEComparison funcs[4]
|
||||
}
|
||||
}
|
||||
|
||||
GLRTexture *tex = render_->CreateTexture(GL_TEXTURE_2D);
|
||||
GLRTexture *tex = render_->CreateTexture(GL_TEXTURE_2D, 256, 1, 1);
|
||||
render_->TextureImage(tex, 0, 256, 1, Draw::DataFormat::R8G8B8A8_UNORM, data);
|
||||
return tex;
|
||||
}
|
||||
|
@ -445,11 +445,6 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
||||
// For the estimate, we assume cluts always point to 8888 for simplicity.
|
||||
cacheSizeEstimate_ += EstimateTexMemoryUsage(entry);
|
||||
|
||||
// Always generate a texture name unless it's a framebuffer, we might need it if the texture is replaced later.
|
||||
if (!entry->textureName) {
|
||||
entry->textureName = render_->CreateTexture(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
if ((entry->bufw == 0 || (gstate.texbufwidth[0] & 0xf800) != 0) && entry->addr >= PSP_GetKernelMemoryEnd()) {
|
||||
ERROR_LOG_REPORT(G3D, "Texture with unexpected bufw (full=%d)", gstate.texbufwidth[0] & 0xffff);
|
||||
// Proceeding here can cause a crash.
|
||||
@ -535,7 +530,7 @@ void TextureCacheGLES::BuildTexture(TexCacheEntry *const entry) {
|
||||
texelsScaledThisFrame_ += w * h;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// GLES2 doesn't have support for a "Max lod" which is critical as PSP games often
|
||||
// don't specify mips all the way down. As a result, we either need to manually generate
|
||||
// the bottom few levels or rely on OpenGL's autogen mipmaps instead, which might not
|
||||
@ -645,6 +640,14 @@ void TextureCacheGLES::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &r
|
||||
|
||||
gpuStats.numTexturesDecoded++;
|
||||
|
||||
if (!entry.textureName) {
|
||||
// TODO: Actually pass in correct size here. The size here is not yet used for anything else
|
||||
// than determining if we can wrap this texture size, that is, it's pow2 or not on very old hardware, else true.
|
||||
// This will be easy after .. well, yet another refactoring, where I hoist the size calculation out of LoadTextureLevel
|
||||
// and unify BuildTexture.
|
||||
entry.textureName = render_->CreateTexture(GL_TEXTURE_2D, 16, 16, 1);
|
||||
}
|
||||
|
||||
if (replaced.GetSize(level, w, h)) {
|
||||
PROFILE_THIS_SCOPE("replacetex");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user