Delete the gl name cache (might resurrect it on the GLQueueRunner side if needed later). Other cleanup and fixes.
This commit is contained in:
parent
46e1fbb788
commit
f3282dcfda
12 changed files with 185 additions and 405 deletions
|
@ -206,7 +206,7 @@ public:
|
|||
return vfb;
|
||||
}
|
||||
}
|
||||
virtual void RebindFramebuffer();
|
||||
void RebindFramebuffer();
|
||||
std::vector<FramebufferInfo> GetFramebufferList();
|
||||
|
||||
void CopyDisplayToOutput();
|
||||
|
|
|
@ -58,8 +58,7 @@ public:
|
|||
void BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
||||
|
||||
virtual void RebindFramebuffer() override;
|
||||
void RebindFramebuffer();
|
||||
|
||||
// TODO: Remove
|
||||
ID3D11Buffer *GetDynamicQuadBuffer() {
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
#include "GPU/GLES/ShaderManagerGLES.h"
|
||||
#include "GPU/GLES/GPU_GLES.h"
|
||||
|
||||
extern const GLuint glprim[8] = {
|
||||
const GLuint glprim[8] = {
|
||||
GL_POINTS,
|
||||
GL_LINES,
|
||||
GL_LINE_STRIP,
|
||||
|
@ -146,17 +146,6 @@ DrawEngineGLES::~DrawEngineGLES() {
|
|||
delete tessDataTransfer;
|
||||
}
|
||||
|
||||
void DrawEngineGLES::RestoreVAO() {
|
||||
if (sharedVao_ != 0) {
|
||||
glBindVertexArray(sharedVao_);
|
||||
} else if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
// Note: this is here because, InitDeviceObjects() is called before GPU_SUPPORTS_VAO is setup.
|
||||
// So, this establishes it if Supports() returns true and there isn't one yet.
|
||||
glGenVertexArrays(1, &sharedVao_);
|
||||
glBindVertexArray(sharedVao_);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawEngineGLES::DeviceLost() {
|
||||
DestroyDeviceObjects();
|
||||
}
|
||||
|
@ -166,20 +155,6 @@ void DrawEngineGLES::DeviceRestore() {
|
|||
}
|
||||
|
||||
void DrawEngineGLES::InitDeviceObjects() {
|
||||
if (bufferNameCache_.empty()) {
|
||||
bufferNameCache_.resize(VERTEXCACHE_NAME_CACHE_SIZE);
|
||||
glGenBuffers(VERTEXCACHE_NAME_CACHE_SIZE, &bufferNameCache_[0]);
|
||||
bufferNameCacheSize_ = 0;
|
||||
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
glGenVertexArrays(1, &sharedVao_);
|
||||
} else {
|
||||
sharedVao_ = 0;
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Device objects already initialized!");
|
||||
}
|
||||
|
||||
for (int i = 0; i < GLRenderManager::MAX_INFLIGHT_FRAMES; i++) {
|
||||
frameData_[i].pushVertex = new GLPushBuffer(render_, GL_ARRAY_BUFFER, 1024 * 1024);
|
||||
frameData_[i].pushIndex = new GLPushBuffer(render_, GL_ELEMENT_ARRAY_BUFFER, 512 * 1024);
|
||||
|
@ -203,18 +178,6 @@ void DrawEngineGLES::DestroyDeviceObjects() {
|
|||
}
|
||||
|
||||
ClearTrackedVertexArrays();
|
||||
if (!bufferNameCache_.empty()) {
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glDeleteBuffers((GLsizei)bufferNameCache_.size(), &bufferNameCache_[0]);
|
||||
bufferNameCache_.clear();
|
||||
bufferNameInfo_.clear();
|
||||
freeSizedBuffers_.clear();
|
||||
bufferNameCacheSize_ = 0;
|
||||
if (sharedVao_ != 0) {
|
||||
glDeleteVertexArrays(1, &sharedVao_);
|
||||
}
|
||||
}
|
||||
|
||||
render_->DeleteInputLayout(softwareInputLayout_);
|
||||
}
|
||||
|
@ -376,11 +339,11 @@ void DrawEngineGLES::DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindO
|
|||
void DrawEngineGLES::MarkUnreliable(VertexArrayInfo *vai) {
|
||||
vai->status = VertexArrayInfo::VAI_UNRELIABLE;
|
||||
if (vai->vbo) {
|
||||
FreeBuffer(vai->vbo);
|
||||
render_->DeleteBuffer(vai->vbo);
|
||||
vai->vbo = 0;
|
||||
}
|
||||
if (vai->ebo) {
|
||||
FreeBuffer(vai->ebo);
|
||||
render_->DeleteBuffer(vai->ebo);
|
||||
vai->ebo = 0;
|
||||
}
|
||||
}
|
||||
|
@ -420,80 +383,14 @@ void DrawEngineGLES::DecimateTrackedVertexArrays() {
|
|||
vai_.Maintain();
|
||||
}
|
||||
|
||||
GLuint DrawEngineGLES::AllocateBuffer(size_t sz) {
|
||||
GLuint unused = 0;
|
||||
|
||||
auto freeMatch = freeSizedBuffers_.find(sz);
|
||||
if (freeMatch != freeSizedBuffers_.end()) {
|
||||
unused = freeMatch->second;
|
||||
_assert_(!bufferNameInfo_[unused].used);
|
||||
|
||||
freeSizedBuffers_.erase(freeMatch);
|
||||
} else {
|
||||
for (GLuint buf : bufferNameCache_) {
|
||||
const BufferNameInfo &info = bufferNameInfo_[buf];
|
||||
if (info.used) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Just pick the first unused one, we'll have to resize it.
|
||||
unused = buf;
|
||||
|
||||
// Let's also remove from the free list, if it's there.
|
||||
if (info.sz != 0) {
|
||||
auto range = freeSizedBuffers_.equal_range(info.sz);
|
||||
for (auto it = range.first; it != range.second; ++it) {
|
||||
if (it->second == buf) {
|
||||
// It will only be once, so remove and bail.
|
||||
freeSizedBuffers_.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unused == 0) {
|
||||
size_t oldSize = bufferNameCache_.size();
|
||||
bufferNameCache_.resize(oldSize + VERTEXCACHE_NAME_CACHE_SIZE);
|
||||
glGenBuffers(VERTEXCACHE_NAME_CACHE_SIZE, &bufferNameCache_[oldSize]);
|
||||
|
||||
unused = bufferNameCache_[oldSize];
|
||||
}
|
||||
|
||||
BufferNameInfo &info = bufferNameInfo_[unused];
|
||||
|
||||
// Record the change in size.
|
||||
bufferNameCacheSize_ += sz - info.sz;
|
||||
info.sz = sz;
|
||||
info.used = true;
|
||||
return unused;
|
||||
}
|
||||
|
||||
void DrawEngineGLES::FreeBuffer(GLuint buf) {
|
||||
// We can reuse buffers by setting new data on them, so let's actually keep it.
|
||||
auto it = bufferNameInfo_.find(buf);
|
||||
if (it != bufferNameInfo_.end()) {
|
||||
it->second.used = false;
|
||||
it->second.lastFrame = gpuStats.numFlips;
|
||||
|
||||
if (it->second.sz != 0) {
|
||||
freeSizedBuffers_.insert(std::make_pair(it->second.sz, buf));
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(G3D, "Unexpected buffer freed (%d) but not tracked", buf);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawEngineGLES::FreeVertexArray(VertexArrayInfo *vai) {
|
||||
if (vai->vbo) {
|
||||
FreeBuffer(vai->vbo);
|
||||
vai->vbo = 0;
|
||||
render_->DeleteBuffer(vai->vbo);
|
||||
vai->vbo = nullptr;
|
||||
}
|
||||
if (vai->ebo) {
|
||||
FreeBuffer(vai->ebo);
|
||||
vai->ebo = 0;
|
||||
render_->DeleteBuffer(vai->ebo);
|
||||
vai->ebo = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -517,7 +414,6 @@ void DrawEngineGLES::DoFlush() {
|
|||
uint32_t indexBufferOffset = 0;
|
||||
|
||||
if (vshader->UseHWTransform()) {
|
||||
GLuint vbo = 0, ebo = 0;
|
||||
int vertexCount = 0;
|
||||
bool useElements = true;
|
||||
|
||||
|
@ -611,31 +507,28 @@ void DrawEngineGLES::DoFlush() {
|
|||
_dbg_assert_msg_(G3D, gstate_c.vertBounds.minV >= gstate_c.vertBounds.maxV, "Should not have checked UVs when caching.");
|
||||
|
||||
size_t vsz = dec_->GetDecVtxFmt().stride * indexGen.MaxIndex();
|
||||
vai->vbo = AllocateBuffer(vsz);
|
||||
glstate.arrayBuffer.bind(vai->vbo);
|
||||
glBufferData(GL_ARRAY_BUFFER, vsz, decoded, GL_STATIC_DRAW);
|
||||
vai->vbo = render_->CreateBuffer(GL_ARRAY_BUFFER, vsz, GL_STATIC_DRAW);
|
||||
render_->BufferSubdata(vai->vbo, 0, vsz, decoded);
|
||||
render_->BindVertexBuffer(vai->vbo);
|
||||
// If there's only been one primitive type, and it's either TRIANGLES, LINES or POINTS,
|
||||
// there is no need for the index buffer we built. We can then use glDrawArrays instead
|
||||
// for a very minor speed boost.
|
||||
if (useElements) {
|
||||
size_t esz = sizeof(short) * indexGen.VertexCount();
|
||||
vai->ebo = AllocateBuffer(esz);
|
||||
glstate.elementArrayBuffer.bind(vai->ebo);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, esz, (GLvoid *)decIndex, GL_STATIC_DRAW);
|
||||
vai->ebo = render_->CreateBuffer(GL_ARRAY_BUFFER, esz, GL_STATIC_DRAW);
|
||||
render_->BufferSubdata(vai->ebo, 0, esz, (uint8_t *)decIndex, false);
|
||||
} else {
|
||||
vai->ebo = 0;
|
||||
glstate.elementArrayBuffer.bind(vai->ebo);
|
||||
render_->BindIndexBuffer(vai->ebo);
|
||||
}
|
||||
} else {
|
||||
gpuStats.numCachedDrawCalls++;
|
||||
glstate.arrayBuffer.bind(vai->vbo);
|
||||
glstate.elementArrayBuffer.bind(vai->ebo);
|
||||
useElements = vai->ebo ? true : false;
|
||||
gpuStats.numCachedVertsDrawn += vai->numVerts;
|
||||
gstate_c.vertexFullAlpha = vai->flags & VAI_FLAG_VERTEXFULLALPHA;
|
||||
}
|
||||
vbo = vai->vbo;
|
||||
ebo = vai->ebo;
|
||||
vertexBuffer = vai->vbo;
|
||||
indexBuffer = vai->ebo;
|
||||
vertexCount = vai->numVerts;
|
||||
prim = static_cast<GEPrimitiveType>(vai->prim);
|
||||
break;
|
||||
|
@ -650,10 +543,8 @@ void DrawEngineGLES::DoFlush() {
|
|||
}
|
||||
gpuStats.numCachedDrawCalls++;
|
||||
gpuStats.numCachedVertsDrawn += vai->numVerts;
|
||||
vbo = vai->vbo;
|
||||
ebo = vai->ebo;
|
||||
glstate.arrayBuffer.bind(vbo);
|
||||
glstate.elementArrayBuffer.bind(ebo);
|
||||
vertexBuffer = vai->vbo;
|
||||
indexBuffer = vai->ebo;
|
||||
vertexCount = vai->numVerts;
|
||||
prim = static_cast<GEPrimitiveType>(vai->prim);
|
||||
|
||||
|
@ -843,108 +734,12 @@ rotateVBO:
|
|||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
}
|
||||
|
||||
GLuint DrawEngineGLES::BindBuffer(const void *p, size_t sz) {
|
||||
// Get a new buffer each time we need one.
|
||||
GLuint buf = AllocateBuffer(sz);
|
||||
glstate.arrayBuffer.bind(buf);
|
||||
|
||||
// These aren't used more than once per frame, so let's use GL_STREAM_DRAW.
|
||||
glBufferData(GL_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW);
|
||||
buffersThisFrame_.push_back(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
GLuint DrawEngineGLES::BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2) {
|
||||
GLuint buf = AllocateBuffer(sz1 + sz2);
|
||||
glstate.arrayBuffer.bind(buf);
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, sz1 + sz2, nullptr, GL_STREAM_DRAW);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, sz1, p1);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, sz1, sz2, p2);
|
||||
buffersThisFrame_.push_back(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
GLuint DrawEngineGLES::BindElementBuffer(const void *p, size_t sz) {
|
||||
GLuint buf = AllocateBuffer(sz);
|
||||
glstate.elementArrayBuffer.bind(buf);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sz, p, GL_STREAM_DRAW);
|
||||
buffersThisFrame_.push_back(buf);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void DrawEngineGLES::DecimateBuffers() {
|
||||
for (GLuint buf : buffersThisFrame_) {
|
||||
FreeBuffer(buf);
|
||||
}
|
||||
buffersThisFrame_.clear();
|
||||
|
||||
if (--bufferDecimationCounter_ <= 0) {
|
||||
bufferDecimationCounter_ = VERTEXCACHE_DECIMATION_INTERVAL;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
// Let's not keep too many around, will eat up memory.
|
||||
// First check if there's any to free, and only check if it seems somewhat full.
|
||||
bool hasOld = false;
|
||||
if (bufferNameCacheSize_ > VERTEXCACHE_NAME_CACHE_FULL_BYTES) {
|
||||
for (GLuint buf : bufferNameCache_) {
|
||||
const BufferNameInfo &info = bufferNameInfo_[buf];
|
||||
const int age = gpuStats.numFlips - info.lastFrame;
|
||||
if (!info.used && age > VERTEXCACHE_NAME_CACHE_MAX_AGE) {
|
||||
hasOld = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hasOld) {
|
||||
// Okay, it is. Let's rebuild the array.
|
||||
std::vector<GLuint> toFree;
|
||||
std::vector<GLuint> toKeep;
|
||||
|
||||
toKeep.reserve(bufferNameCache_.size());
|
||||
|
||||
for (size_t i = 0, n = bufferNameCache_.size(); i < n; ++i) {
|
||||
const GLuint buf = bufferNameCache_[i];
|
||||
const BufferNameInfo &info = bufferNameInfo_[buf];
|
||||
const int age = gpuStats.numFlips - info.lastFrame;
|
||||
if (!info.used && age > VERTEXCACHE_NAME_CACHE_MAX_AGE) {
|
||||
toFree.push_back(buf);
|
||||
bufferNameCacheSize_ -= bufferNameInfo_[buf].sz;
|
||||
bufferNameInfo_.erase(buf);
|
||||
|
||||
// If we've removed all we want to this round, keep the rest and abort.
|
||||
if (toFree.size() >= VERTEXCACHE_NAME_DECIMATION_MAX && i + 1 < bufferNameCache_.size()) {
|
||||
toKeep.insert(toKeep.end(), bufferNameCache_.begin() + i + 1, bufferNameCache_.end());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
toKeep.push_back(buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (!toFree.empty()) {
|
||||
bufferNameCache_ = toKeep;
|
||||
// TODO: Rebuild?
|
||||
freeSizedBuffers_.clear();
|
||||
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glDeleteBuffers((GLsizei)toFree.size(), &toFree[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DrawEngineGLES::IsCodePtrVertexDecoder(const u8 *ptr) const {
|
||||
return decJitCache_->IsInSpace(ptr);
|
||||
}
|
||||
|
||||
void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) {
|
||||
/*
|
||||
#ifndef USING_GLES2
|
||||
if (isAllowTexture1D_) {
|
||||
// Position
|
||||
|
@ -1041,4 +836,5 @@ void DrawEngineGLES::TessellationDataTransferGLES::SendDataToShader(const float
|
|||
}
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
*/
|
||||
}
|
||||
|
|
|
@ -61,8 +61,8 @@ class VertexArrayInfo {
|
|||
public:
|
||||
VertexArrayInfo() {
|
||||
status = VAI_NEW;
|
||||
vbo = 0;
|
||||
ebo = 0;
|
||||
vbo = nullptr;
|
||||
ebo = nullptr;
|
||||
prim = GE_PRIM_INVALID;
|
||||
numDraws = 0;
|
||||
numFrames = 0;
|
||||
|
@ -82,8 +82,8 @@ public:
|
|||
ReliableHashType hash;
|
||||
u32 minihash;
|
||||
|
||||
u32 vbo;
|
||||
u32 ebo;
|
||||
GLRBuffer *vbo;
|
||||
GLRBuffer *ebo;
|
||||
|
||||
// Precalculated parameter for drawRangeElements
|
||||
u16 numVerts;
|
||||
|
@ -119,7 +119,6 @@ public:
|
|||
void SetFragmentTestCache(FragmentTestCacheGLES *testCache) {
|
||||
fragmentTestCache_ = testCache;
|
||||
}
|
||||
void RestoreVAO();
|
||||
|
||||
void DeviceLost();
|
||||
void DeviceRestore();
|
||||
|
@ -151,10 +150,12 @@ public:
|
|||
SubmitPrim(verts, inds, prim, vertexCount, vertType, bytesRead);
|
||||
}
|
||||
|
||||
GLuint BindBuffer(const void *p, size_t sz);
|
||||
GLuint BindBuffer(const void *p1, size_t sz1, const void *p2, size_t sz2);
|
||||
GLuint BindElementBuffer(const void *p, size_t sz);
|
||||
void DecimateBuffers();
|
||||
GLPushBuffer *GetPushVertexBuffer() {
|
||||
return frameData_[render_->GetCurFrame()].pushVertex;
|
||||
}
|
||||
GLPushBuffer *GetPushIndexBuffer() {
|
||||
return frameData_[render_->GetCurFrame()].pushIndex;
|
||||
}
|
||||
|
||||
void ClearInputLayoutMap();
|
||||
|
||||
|
@ -171,8 +172,6 @@ private:
|
|||
|
||||
void DecodeVertsToPushBuffer(GLPushBuffer *push, uint32_t *bindOffset, GLRBuffer **buf);
|
||||
|
||||
GLuint AllocateBuffer(size_t sz);
|
||||
void FreeBuffer(GLuint buf);
|
||||
void FreeVertexArray(VertexArrayInfo *vai);
|
||||
|
||||
void MarkUnreliable(VertexArrayInfo *vai);
|
||||
|
@ -188,23 +187,7 @@ private:
|
|||
DenseHashMap<uint32_t, GLRInputLayout *, nullptr> inputLayoutMap_;
|
||||
|
||||
GLRInputLayout *softwareInputLayout_ = nullptr;
|
||||
|
||||
// Vertex buffer objects
|
||||
// Element buffer objects
|
||||
struct BufferNameInfo {
|
||||
BufferNameInfo() : sz(0), used(false), lastFrame(0) {}
|
||||
|
||||
size_t sz;
|
||||
bool used;
|
||||
int lastFrame;
|
||||
};
|
||||
GLRenderManager *render_;
|
||||
std::vector<GLuint> bufferNameCache_;
|
||||
std::multimap<size_t, GLuint> freeSizedBuffers_;
|
||||
std::unordered_map<GLuint, BufferNameInfo> bufferNameInfo_;
|
||||
std::vector<GLuint> buffersThisFrame_;
|
||||
size_t bufferNameCacheSize_ = 0;
|
||||
GLuint sharedVao_ = 0;
|
||||
|
||||
// Other
|
||||
ShaderManagerGLES *shaderManager_ = nullptr;
|
||||
|
@ -218,15 +201,11 @@ private:
|
|||
// Hardware tessellation
|
||||
class TessellationDataTransferGLES : public TessellationDataTransfer {
|
||||
private:
|
||||
int data_tex[3];
|
||||
GLRTexture *data_tex[3]{};
|
||||
bool isAllowTexture1D_;
|
||||
public:
|
||||
TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), data_tex(), isAllowTexture1D_(isAllowTexture1D) {
|
||||
glGenTextures(3, (GLuint*)data_tex);
|
||||
}
|
||||
~TessellationDataTransferGLES() {
|
||||
glDeleteTextures(3, (GLuint*)data_tex);
|
||||
}
|
||||
TessellationDataTransferGLES(bool isAllowTexture1D) : TessellationDataTransfer(), isAllowTexture1D_(isAllowTexture1D) { }
|
||||
~TessellationDataTransferGLES() { }
|
||||
void SendDataToShader(const float *pos, const float *tex, const float *col, int size, bool hasColor, bool hasTexCoords) override;
|
||||
};
|
||||
};
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "GPU/Common/TextureDecoder.h"
|
||||
#include "GPU/Common/FramebufferCommon.h"
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
#include "ext/native/gfx/GLStateCache.h"
|
||||
#include "GPU/GLES/FramebufferManagerGLES.h"
|
||||
#include "GPU/GLES/TextureCacheGLES.h"
|
||||
#include "GPU/GLES/DrawEngineGLES.h"
|
||||
|
@ -103,13 +102,14 @@ void FramebufferManagerGLES::CompileDraw2DProgram() {
|
|||
static std::string vs_code, fs_code;
|
||||
vs_code = ApplyGLSLPrelude(basic_vs, GL_VERTEX_SHADER);
|
||||
fs_code = ApplyGLSLPrelude(tex_fs, GL_FRAGMENT_SHADER);
|
||||
draw2dprogram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &errorString);
|
||||
if (!draw2dprogram_) {
|
||||
ERROR_LOG_REPORT(G3D, "Failed to compile draw2dprogram! This shouldn't happen.\n%s", errorString.c_str());
|
||||
} else {
|
||||
glsl_bind(draw2dprogram_);
|
||||
glUniform1i(draw2dprogram_->sampler0, 0);
|
||||
}
|
||||
std::vector<GLRShader *> shaders;
|
||||
GLRShader *vs = render_->CreateShader(GL_VERTEX_SHADER, vs_code);
|
||||
GLRShader *fs = render_->CreateShader(GL_FRAGMENT_SHADER, fs_code);
|
||||
std::vector<GLRProgram::UniformLocQuery> queries;
|
||||
queries.push_back({ &u_draw2d_tex, "u_tex" });
|
||||
std::vector<GLRProgram::Initializer> initializers;
|
||||
initializers.push_back({ &u_draw2d_tex, 0 });
|
||||
draw2dprogram_ = render_->CreateProgram(shaders, {}, queries, initializers, false);
|
||||
CompilePostShader();
|
||||
}
|
||||
}
|
||||
|
@ -156,7 +156,26 @@ void FramebufferManagerGLES::CompilePostShader() {
|
|||
}
|
||||
|
||||
if (!translationFailed) {
|
||||
postShaderProgram_ = glsl_create_source(vshader.c_str(), fshader.c_str(), &errorString);
|
||||
SetNumExtraFBOs(1);
|
||||
|
||||
std::vector<GLRShader *> shaders;
|
||||
shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vshader));
|
||||
shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, fshader));
|
||||
std::vector<GLRProgram::UniformLocQuery> queries;
|
||||
queries.push_back({ &u_postShaderTex, "tex" });
|
||||
queries.push_back({ &deltaLoc_, "u_texelDelta" });
|
||||
queries.push_back({ &pixelDeltaLoc_, "u_pixelDelta" });
|
||||
queries.push_back({ &timeLoc_, "u_time" });
|
||||
queries.push_back({ &videoLoc_, "u_video" });
|
||||
|
||||
std::vector<GLRProgram::Initializer> inits;
|
||||
inits.push_back({ &u_postShaderTex, 0, 0 });
|
||||
postShaderProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false);
|
||||
render_->SetUniformI1(&u_postShaderTex, 0);
|
||||
|
||||
for (auto iter : shaders) {
|
||||
render_->DeleteShader(iter);
|
||||
}
|
||||
} else {
|
||||
ERROR_LOG(FRAMEBUF, "Failed to translate post shader!");
|
||||
}
|
||||
|
@ -194,13 +213,6 @@ void FramebufferManagerGLES::CompilePostShader() {
|
|||
}
|
||||
usePostShader_ = false;
|
||||
} else {
|
||||
glsl_bind(postShaderProgram_);
|
||||
glUniform1i(postShaderProgram_->sampler0, 0);
|
||||
SetNumExtraFBOs(1);
|
||||
deltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_texelDelta");
|
||||
pixelDeltaLoc_ = glsl_uniform_loc(postShaderProgram_, "u_pixelDelta");
|
||||
timeLoc_ = glsl_uniform_loc(postShaderProgram_, "u_time");
|
||||
videoLoc_ = glsl_uniform_loc(postShaderProgram_, "u_video");
|
||||
usePostShader_ = true;
|
||||
}
|
||||
} else {
|
||||
|
@ -211,7 +223,7 @@ void FramebufferManagerGLES::CompilePostShader() {
|
|||
}
|
||||
|
||||
void FramebufferManagerGLES::Bind2DShader() {
|
||||
glsl_bind(draw2dprogram_);
|
||||
render_->BindProgram(draw2dprogram_);
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms) {
|
||||
|
@ -219,20 +231,20 @@ void FramebufferManagerGLES::BindPostShader(const PostShaderUniforms &uniforms)
|
|||
if (!postShaderProgram_) {
|
||||
CompileDraw2DProgram();
|
||||
}
|
||||
|
||||
glsl_bind(postShaderProgram_);
|
||||
render_->BindProgram(postShaderProgram_);
|
||||
if (deltaLoc_ != -1)
|
||||
glUniform2f(deltaLoc_, uniforms.texelDelta[0], uniforms.texelDelta[1]);
|
||||
render_->SetUniformF(&deltaLoc_, 2, uniforms.texelDelta);
|
||||
if (pixelDeltaLoc_ != -1)
|
||||
glUniform2f(pixelDeltaLoc_, uniforms.pixelDelta[0], uniforms.pixelDelta[1]);
|
||||
render_->SetUniformF(&pixelDeltaLoc_, 2, uniforms.pixelDelta);
|
||||
if (timeLoc_ != -1)
|
||||
glUniform4fv(timeLoc_, 1, uniforms.time);
|
||||
render_->SetUniformF(&timeLoc_, 4, uniforms.time);
|
||||
if (videoLoc_ != -1)
|
||||
glUniform1f(videoLoc_, uniforms.video);
|
||||
render_->SetUniformF(&videoLoc_, 1, &uniforms.video);
|
||||
}
|
||||
|
||||
FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) :
|
||||
FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render) :
|
||||
FramebufferManagerCommon(draw),
|
||||
render_(render),
|
||||
drawPixelsTex_(0),
|
||||
drawPixelsTexFormat_(GE_FORMAT_INVALID),
|
||||
convBuf_(nullptr),
|
||||
|
@ -275,15 +287,25 @@ void FramebufferManagerGLES::SetDrawEngine(DrawEngineGLES *td) {
|
|||
|
||||
void FramebufferManagerGLES::CreateDeviceObjects() {
|
||||
CompileDraw2DProgram();
|
||||
|
||||
std::vector<GLRInputLayout::Entry> entries;
|
||||
entries.push_back({ 0, 3, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, pos) });
|
||||
entries.push_back({ 0, 2, GL_FLOAT, GL_FALSE, sizeof(Simple2DVertex), offsetof(Simple2DVertex, uv) });
|
||||
simple2DInputLayout_ = render_->CreateInputLayout(entries);
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::DestroyDeviceObjects() {
|
||||
if (simple2DInputLayout_) {
|
||||
render_->DeleteInputLayout(simple2DInputLayout_);
|
||||
simple2DInputLayout_ = nullptr;
|
||||
}
|
||||
|
||||
if (draw2dprogram_) {
|
||||
glsl_destroy(draw2dprogram_);
|
||||
render_->DeleteProgram(draw2dprogram_);
|
||||
draw2dprogram_ = nullptr;
|
||||
}
|
||||
if (postShaderProgram_) {
|
||||
glsl_destroy(postShaderProgram_);
|
||||
render_->DeleteProgram(postShaderProgram_);
|
||||
postShaderProgram_ = nullptr;
|
||||
}
|
||||
if (drawPixelsTex_) {
|
||||
|
@ -291,7 +313,7 @@ void FramebufferManagerGLES::DestroyDeviceObjects() {
|
|||
drawPixelsTex_ = 0;
|
||||
}
|
||||
if (stencilUploadProgram_) {
|
||||
glsl_destroy(stencilUploadProgram_);
|
||||
render_->DeleteProgram(stencilUploadProgram_);
|
||||
stencilUploadProgram_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -329,15 +351,10 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma
|
|||
drawPixelsTexW_ = texWidth;
|
||||
drawPixelsTexH_ = height;
|
||||
|
||||
/*
|
||||
// Initialize backbuffer texture for DrawPixels
|
||||
glBindTexture(GL_TEXTURE_2D, drawPixelsTex_);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
render_->BindTexture(0, drawPixelsTex_);
|
||||
render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f);
|
||||
|
||||
/*
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
*/
|
||||
drawPixelsTexFormat_ = srcPixelFormat;
|
||||
|
@ -392,7 +409,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma
|
|||
}
|
||||
|
||||
void FramebufferManagerGLES::SetViewport2D(int x, int y, int w, int h) {
|
||||
glstate.viewport.set(x, y, w, h);
|
||||
render_->SetViewport({ (float)x, (float)y, (float)w, (float)h, 0.0f, 1.0f });
|
||||
}
|
||||
|
||||
// x, y, w, h are relative coordinates against destW/destH, which is not very intuitive.
|
||||
|
@ -405,7 +422,7 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float
|
|||
u0,v1,
|
||||
};
|
||||
|
||||
static const GLushort indices[4] = {0,1,3,2};
|
||||
static const GLushort indices[4] = { 0,1,3,2 };
|
||||
|
||||
if (uvRotation != ROTATION_LOCKED_HORIZONTAL) {
|
||||
float temp[8];
|
||||
|
@ -424,9 +441,9 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float
|
|||
|
||||
float pos[12] = {
|
||||
x,y,0,
|
||||
x+w,y,0,
|
||||
x+w,y+h,0,
|
||||
x,y+h,0
|
||||
x + w,y,0,
|
||||
x + w,y + h,0,
|
||||
x,y + h,0
|
||||
};
|
||||
|
||||
float invDestW = 1.0f / (destW * 0.5f);
|
||||
|
@ -438,11 +455,9 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float
|
|||
|
||||
// Upscaling postshaders doesn't look well with linear
|
||||
if (flags & DRAWTEX_LINEAR) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_LINEAR, GL_LINEAR, 0.0f);
|
||||
} else {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f);
|
||||
}
|
||||
|
||||
const GLSLProgram *program = glsl_get_program();
|
||||
|
@ -450,30 +465,23 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float
|
|||
ERROR_LOG(FRAMEBUF, "Trying to DrawActiveTexture() without a program");
|
||||
return;
|
||||
}
|
||||
Simple2DVertex verts[4];
|
||||
memcpy(verts[0].pos, &pos[0], 12);
|
||||
memcpy(verts[1].pos, &pos[3], 12);
|
||||
memcpy(verts[3].pos, &pos[6], 12);
|
||||
memcpy(verts[2].pos, &pos[9], 12);
|
||||
memcpy(verts[0].uv, &texCoords[0], 8);
|
||||
memcpy(verts[1].uv, &texCoords[2], 8);
|
||||
memcpy(verts[3].uv, &texCoords[4], 8);
|
||||
memcpy(verts[2].uv, &texCoords[6], 8);
|
||||
|
||||
glEnableVertexAttribArray(program->a_position);
|
||||
glEnableVertexAttribArray(program->a_texcoord0);
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
drawEngineGL_->BindBuffer(pos, sizeof(pos), texCoords, sizeof(texCoords));
|
||||
drawEngineGL_->BindElementBuffer(indices, sizeof(indices));
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, 0);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, (void *)sizeof(pos));
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, 0);
|
||||
} else {
|
||||
glstate.arrayBuffer.unbind();
|
||||
glstate.elementArrayBuffer.unbind();
|
||||
glVertexAttribPointer(program->a_position, 3, GL_FLOAT, GL_FALSE, 12, pos);
|
||||
glVertexAttribPointer(program->a_texcoord0, 2, GL_FLOAT, GL_FALSE, 8, texCoords);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_SHORT, indices);
|
||||
}
|
||||
glDisableVertexAttribArray(program->a_position);
|
||||
glDisableVertexAttribArray(program->a_texcoord0);
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::RebindFramebuffer() {
|
||||
FramebufferManagerCommon::RebindFramebuffer();
|
||||
if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE)
|
||||
glstate.viewport.restore();
|
||||
uint32_t bindOffset;
|
||||
GLRBuffer *buffer;
|
||||
void *dest = drawEngineGL_->GetPushVertexBuffer()->Push(sizeof(verts), &bindOffset, &buffer);
|
||||
memcpy(dest, verts, sizeof(verts));
|
||||
render_->BindVertexBuffer(buffer);
|
||||
render_->BindInputLayout(simple2DInputLayout_, (void *)(intptr_t)bindOffset);
|
||||
render_->Draw(GL_TRIANGLE_STRIP, 0, 4);
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) {
|
||||
|
@ -514,17 +522,15 @@ void FramebufferManagerGLES::BlitFramebufferDepth(VirtualFramebuffer *src, Virtu
|
|||
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT)) {
|
||||
// Let's only do this if not clearing depth.
|
||||
glstate.scissorTest.force(false);
|
||||
draw_->BlitFramebuffer(src->fbo, 0, 0, w, h, dst->fbo, 0, 0, w, h, Draw::FB_DEPTH_BIT, Draw::FB_BLIT_NEAREST);
|
||||
dst->last_frame_depth_updated = gpuStats.numFlips;
|
||||
glstate.scissorTest.restore();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (!framebuffer->fbo || !useBufferedRendering_) {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
render_->BindTexture(0, nullptr);
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_BAD_FB_TEXTURE;
|
||||
return;
|
||||
}
|
||||
|
@ -691,7 +697,6 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
|
|||
}
|
||||
}
|
||||
|
||||
glstate.scissorTest.force(false);
|
||||
if (useBlit) {
|
||||
draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST);
|
||||
} else {
|
||||
|
@ -701,38 +706,21 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX,
|
|||
// Make sure our 2D drawing program is ready. Compiles only if not already compiled.
|
||||
CompileDraw2DProgram();
|
||||
|
||||
glstate.viewport.force(0, 0, dst->renderWidth, dst->renderHeight);
|
||||
glstate.blend.force(false);
|
||||
glstate.cullFace.force(false);
|
||||
glstate.depthTest.force(false);
|
||||
glstate.stencilTest.force(false);
|
||||
#if !defined(USING_GLES2)
|
||||
glstate.colorLogicOp.force(false);
|
||||
#endif
|
||||
glstate.colorMask.force(true, true, true, true);
|
||||
glstate.stencilMask.force(0xFF);
|
||||
render_->SetViewport({ 0, 0, (float)dst->renderWidth, (float)dst->renderHeight, 0, 1.0f });
|
||||
render_->SetStencilDisabled();
|
||||
render_->SetDepth(false, false, GL_ALWAYS);
|
||||
render_->SetNoBlendAndMask(0xF);
|
||||
|
||||
// The first four coordinates are relative to the 6th and 7th arguments of DrawActiveTexture.
|
||||
// Should maybe revamp that interface.
|
||||
float srcW = src->bufferWidth;
|
||||
float srcH = src->bufferHeight;
|
||||
glsl_bind(draw2dprogram_);
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
textureCacheGL_->ForgetLastTexture();
|
||||
glstate.viewport.restore();
|
||||
glstate.blend.restore();
|
||||
glstate.cullFace.restore();
|
||||
glstate.depthTest.restore();
|
||||
glstate.stencilTest.restore();
|
||||
#if !defined(USING_GLES2)
|
||||
glstate.colorLogicOp.restore();
|
||||
#endif
|
||||
glstate.colorMask.restore();
|
||||
glstate.stencilMask.restore();
|
||||
}
|
||||
|
||||
glstate.scissorTest.restore();
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_RASTER_STATE);
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
}
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@ struct AsyncPBO {
|
|||
|
||||
class FramebufferManagerGLES : public FramebufferManagerCommon {
|
||||
public:
|
||||
FramebufferManagerGLES(Draw::DrawContext *draw);
|
||||
FramebufferManagerGLES(Draw::DrawContext *draw, GLRenderManager *render);
|
||||
~FramebufferManagerGLES();
|
||||
|
||||
void SetTextureCache(TextureCacheGLES *tc);
|
||||
|
@ -82,7 +82,6 @@ public:
|
|||
bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override;
|
||||
|
||||
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
|
||||
virtual void RebindFramebuffer() override;
|
||||
|
||||
void DeviceRestore(Draw::DrawContext *draw);
|
||||
|
||||
|
@ -104,7 +103,6 @@ private:
|
|||
void Bind2DShader() override;
|
||||
void BindPostShader(const PostShaderUniforms &uniforms) override;
|
||||
void CompileDraw2DProgram();
|
||||
void DestroyDraw2DProgram();
|
||||
void CompilePostShader();
|
||||
|
||||
void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently
|
||||
|
@ -121,19 +119,34 @@ private:
|
|||
|
||||
u8 *convBuf_;
|
||||
u32 convBufSize_;
|
||||
GLSLProgram *draw2dprogram_ = nullptr;
|
||||
GLSLProgram *postShaderProgram_ = nullptr;
|
||||
GLSLProgram *stencilUploadProgram_ = nullptr;
|
||||
int plainColorLoc_;
|
||||
int videoLoc_;
|
||||
int timeLoc_;
|
||||
int pixelDeltaLoc_;
|
||||
int deltaLoc_;
|
||||
GLRProgram *draw2dprogram_ = nullptr;
|
||||
GLRProgram *postShaderProgram_ = nullptr;
|
||||
|
||||
|
||||
GLRProgram *stencilUploadProgram_ = nullptr;
|
||||
int u_stencilUploadTex = -1;
|
||||
int u_stencilValue = -1;
|
||||
int u_postShaderTex = -1;
|
||||
|
||||
// Cached uniform locs
|
||||
int u_draw2d_tex = -1;
|
||||
|
||||
int plainColorLoc_ = -1;
|
||||
int videoLoc_ = -1;
|
||||
int timeLoc_ = -1;
|
||||
int pixelDeltaLoc_ = -1;
|
||||
int deltaLoc_ = -1;
|
||||
|
||||
TextureCacheGLES *textureCacheGL_;
|
||||
ShaderManagerGLES *shaderManagerGL_;
|
||||
DrawEngineGLES *drawEngineGL_;
|
||||
|
||||
struct Simple2DVertex {
|
||||
float pos[3];
|
||||
float uv[2];
|
||||
};
|
||||
GLRInputLayout *simple2DInputLayout_;
|
||||
|
||||
// Not used under ES currently.
|
||||
AsyncPBO *pixelBufObj_; //this isn't that large
|
||||
u8 currentPBO_;
|
||||
|
|
|
@ -86,7 +86,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
GLRenderManager *render = (GLRenderManager *)draw->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
|
||||
shaderManagerGL_ = new ShaderManagerGLES(render);
|
||||
framebufferManagerGL_ = new FramebufferManagerGLES(draw);
|
||||
framebufferManagerGL_ = new FramebufferManagerGLES(draw, render);
|
||||
framebufferManager_ = framebufferManagerGL_;
|
||||
textureCacheGL_ = new TextureCacheGLES(draw);
|
||||
textureCache_ = textureCacheGL_;
|
||||
|
@ -163,7 +163,6 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
|||
// 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();
|
||||
drawEngine_.RestoreVAO();
|
||||
textureCacheGL_->NotifyConfigChanged();
|
||||
|
||||
// Load shader cache.
|
||||
|
@ -498,7 +497,6 @@ void GPU_GLES::UpdateCmdInfo() {
|
|||
}
|
||||
|
||||
void GPU_GLES::ReapplyGfxState() {
|
||||
drawEngine_.RestoreVAO();
|
||||
glstate.Restore();
|
||||
GPUCommon::ReapplyGfxState();
|
||||
}
|
||||
|
@ -509,7 +507,6 @@ void GPU_GLES::BeginFrame() {
|
|||
|
||||
textureCacheGL_->StartFrame();
|
||||
drawEngine_.DecimateTrackedVertexArrays();
|
||||
drawEngine_.DecimateBuffers();
|
||||
depalShaderCache_.Decimate();
|
||||
fragmentTestCache_.Decimate();
|
||||
|
||||
|
|
|
@ -126,26 +126,32 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
|||
static std::string vs_code, fs_code;
|
||||
vs_code = ApplyGLSLPrelude(stencil_vs, GL_VERTEX_SHADER);
|
||||
fs_code = ApplyGLSLPrelude(stencil_fs, GL_FRAGMENT_SHADER);
|
||||
stencilUploadProgram_ = glsl_create_source(vs_code.c_str(), fs_code.c_str(), &errorString);
|
||||
std::vector<GLRShader *> shaders;
|
||||
shaders.push_back(render_->CreateShader(GL_VERTEX_SHADER, vs_code));
|
||||
shaders.push_back(render_->CreateShader(GL_FRAGMENT_SHADER, fs_code));
|
||||
std::vector<GLRProgram::UniformLocQuery> queries;
|
||||
queries.push_back({ &u_stencilUploadTex, "tex" });
|
||||
std::vector<GLRProgram::Initializer> inits;
|
||||
inits.push_back({ &u_stencilUploadTex, 0, 0 });
|
||||
stencilUploadProgram_ = render_->CreateProgram(shaders, {}, queries, inits, false);
|
||||
for (auto iter : shaders) {
|
||||
render_->DeleteShader(iter);
|
||||
}
|
||||
if (!stencilUploadProgram_) {
|
||||
ERROR_LOG_REPORT(G3D, "Failed to compile stencilUploadProgram! This shouldn't happen.\n%s", errorString.c_str());
|
||||
} else {
|
||||
glsl_bind(stencilUploadProgram_);
|
||||
render_->BindProgram(stencilUploadProgram_);
|
||||
}
|
||||
|
||||
GLint u_tex = glsl_uniform_loc(stencilUploadProgram_, "tex");
|
||||
glUniform1i(u_tex, 0);
|
||||
} else {
|
||||
glsl_bind(stencilUploadProgram_);
|
||||
render_->BindProgram(stencilUploadProgram_);
|
||||
}
|
||||
|
||||
shaderManagerGL_->DirtyLastShader();
|
||||
|
||||
DisableState();
|
||||
glstate.colorMask.set(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
|
||||
render_->SetNoBlendAndMask(0x8);
|
||||
glstate.stencilTest.enable();
|
||||
glstate.stencilOp.set(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE);
|
||||
|
||||
bool useBlit = gstate_c.Supports(GPU_SUPPORTS_ARB_FRAMEBUFFER_BLIT | GPU_SUPPORTS_NV_FRAMEBUFFER_BLIT);
|
||||
|
||||
|
@ -164,43 +170,41 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe
|
|||
} else if (dstBuffer->fbo) {
|
||||
draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP, Draw::RPAction::CLEAR });
|
||||
}
|
||||
glViewport(0, 0, w, h);
|
||||
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
render_->SetViewport({ 0, 0, (float)w, (float)h, 0.0f, 1.0f });
|
||||
|
||||
float u1 = 1.0f;
|
||||
float v1 = 1.0f;
|
||||
MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1);
|
||||
textureCacheGL_->ForgetLastTexture();
|
||||
|
||||
glClearStencil(0);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
render_->Clear(0, 0, 0, GL_STENCIL_BUFFER_BIT);
|
||||
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, 0xFF, 0xFF, 0xFF);
|
||||
|
||||
glstate.stencilFunc.set(GL_ALWAYS, 0xFF, 0xFF);
|
||||
|
||||
GLint u_stencilValue = glsl_uniform_loc(stencilUploadProgram_, "u_stencilValue");
|
||||
for (int i = 1; i < values; i += i) {
|
||||
if (!(usedBits & i)) {
|
||||
// It's already zero, let's skip it.
|
||||
continue;
|
||||
}
|
||||
if (dstBuffer->format == GE_FORMAT_4444) {
|
||||
glstate.stencilMask.set((i << 4) | i);
|
||||
glUniform1f(u_stencilValue, i * (16.0f / 255.0f));
|
||||
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, (i << 4) | i, 0xFF, 0xFF);
|
||||
render_->SetUniformF1(&u_stencilValue, i * (16.0f / 255.0f));
|
||||
} else if (dstBuffer->format == GE_FORMAT_5551) {
|
||||
glstate.stencilMask.set(0xFF);
|
||||
glUniform1f(u_stencilValue, i * (128.0f / 255.0f));
|
||||
render_->SetUniformF1(&u_stencilValue, i * (128.0f / 255.0f));
|
||||
} else {
|
||||
glstate.stencilMask.set(i);
|
||||
glUniform1f(u_stencilValue, i * (1.0f / 255.0f));
|
||||
render_->SetStencil(GL_TRUE, GL_ALWAYS, GL_KEEP, GL_KEEP, GL_KEEP, i, 0xFF, 0xFF);
|
||||
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);
|
||||
}
|
||||
glstate.stencilMask.set(0xFF);
|
||||
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);
|
||||
}
|
||||
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VIEWPORTSCISSOR_STATE);
|
||||
|
||||
RebindFramebuffer();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -401,6 +401,7 @@ public:
|
|||
void Use(GLRenderManager *render, DrawEngineGLES *transformDraw) {
|
||||
render->BindProgram(shader_->program);
|
||||
|
||||
/*
|
||||
// Restore will rebind all of the state below.
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_VAO)) {
|
||||
static const GLubyte indices[4] = { 0, 1, 3, 2 };
|
||||
|
@ -412,11 +413,12 @@ public:
|
|||
}
|
||||
glEnableVertexAttribArray(shader_->a_position);
|
||||
glEnableVertexAttribArray(shader_->a_texcoord0);
|
||||
*/
|
||||
}
|
||||
|
||||
void Shade() {
|
||||
static const GLubyte indices[4] = { 0, 1, 3, 2 };
|
||||
|
||||
/*
|
||||
glstate.blend.force(false);
|
||||
glstate.colorMask.force(true, true, true, true);
|
||||
glstate.scissorTest.force(false);
|
||||
|
@ -441,6 +443,7 @@ public:
|
|||
glDisableVertexAttribArray(shader_->a_texcoord0);
|
||||
|
||||
glstate.Restore();
|
||||
*/
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -473,8 +476,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram
|
|||
render_->BindTexture(3, clutTexture);
|
||||
|
||||
framebufferManagerGL_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
render_->SetTextureSampler(GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f);
|
||||
|
||||
shaderApply.Shade();
|
||||
|
||||
|
@ -496,8 +498,6 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram
|
|||
framebufferManagerGL_->RebindFramebuffer();
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
|
||||
CHECK_GL_ERROR_IF_DEBUG();
|
||||
|
||||
InvalidateLastTexture();
|
||||
}
|
||||
|
||||
|
|
|
@ -99,16 +99,7 @@ void GLQueueRunner::RunInitSteps(const std::vector<GLRInitStep> &steps) {
|
|||
break;
|
||||
}
|
||||
|
||||
// Auto-initialize samplers.
|
||||
glUseProgram(program->program);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
char temp[256];
|
||||
sprintf(temp, "Sampler%i", i);
|
||||
int samplerLoc = glGetUniformLocation(program->program, temp);
|
||||
if (samplerLoc != -1) {
|
||||
glUniform1i(samplerLoc, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Query all the uniforms.
|
||||
for (int i = 0; i < program->queries_.size(); i++) {
|
||||
|
|
|
@ -318,6 +318,8 @@ private:
|
|||
GLuint globalVAO_;
|
||||
|
||||
GLint curFramebuffer_ = 0;
|
||||
int curFBWidth_;
|
||||
int curFBHeight_;
|
||||
|
||||
// Readback buffer. Currently we only support synchronous readback, so we only really need one.
|
||||
// We size it generously.
|
||||
|
|
|
@ -122,7 +122,7 @@ public:
|
|||
glDeleteBuffers(1, &buffer);
|
||||
}
|
||||
}
|
||||
GLuint buffer;
|
||||
GLuint buffer = 0;
|
||||
GLuint target_;
|
||||
private:
|
||||
};
|
||||
|
@ -216,6 +216,8 @@ public:
|
|||
return step.create_framebuffer.framebuffer;
|
||||
}
|
||||
|
||||
// Can't replace uniform initializers with direct calls to SetUniform() etc because there might
|
||||
// not be an active render pass.
|
||||
GLRProgram *CreateProgram(
|
||||
std::vector<GLRShader *> shaders, std::vector<GLRProgram::Semantic> semantics, std::vector<GLRProgram::UniformLocQuery> queries,
|
||||
std::vector<GLRProgram::Initializer> initalizers, bool supportDualSource) {
|
||||
|
@ -398,6 +400,15 @@ public:
|
|||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
void SetUniformF1(GLint *loc, const float udata) {
|
||||
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
|
||||
GLRRenderData data{ GLRRenderCommand::UNIFORM4F };
|
||||
data.uniform4.loc = loc;
|
||||
data.uniform4.count = 1;
|
||||
memcpy(data.uniform4.v, &udata, sizeof(float));
|
||||
curRenderStep_->commands.push_back(data);
|
||||
}
|
||||
|
||||
void SetUniformF(const char *name, int count, const float *udata) {
|
||||
_dbg_assert_(G3D, curRenderStep_ && curRenderStep_->stepType == GLRStepType::RENDER);
|
||||
GLRRenderData data{ GLRRenderCommand::UNIFORM4F };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue