Merge pull request #9329 from hrydgard/shield-texture-fix

Assorted cleanup of GL texture handling. Fixes #9286
This commit is contained in:
Henrik Rydgård
2017-02-19 13:12:02 +01:00
committed by GitHub
10 changed files with 215 additions and 195 deletions
+1 -1
View File
@@ -82,7 +82,7 @@ public:
}
protected:
void SetViewport2D(int x, int y, int w, int h);
void SetViewport2D(int x, int y, int w, int h) override;
void DisableState() override;
void ClearBuffer(bool keepState = false) override;
void FlushBeforeCopy() override;
+69 -61
View File
@@ -58,15 +58,7 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
: GPUCommon(gfxCtx, draw)
{
using namespace Draw;
TextureDesc desc{};
desc.type = TextureType::LINEAR2D;
desc.format = DataFormat::R8G8B8A8_UNORM;
desc.width = 480;
desc.height = 272;
desc.depth = 1;
desc.mipLevels = 1;
fbTex = draw_->CreateTexture(desc);
fbTex = nullptr;
InputLayoutDesc inputDesc = {
{
{ sizeof(Vertex), false },
@@ -124,9 +116,10 @@ SoftGPU::~SoftGPU() {
texColor->Release();
texColor = nullptr;
fbTex->Release();
fbTex = nullptr;
if (fbTex) {
fbTex->Release();
fbTex = nullptr;
}
vdata->Release();
vdata = nullptr;
idata->Release();
@@ -147,32 +140,38 @@ void SoftGPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for
// Copies RGBA8 data from RAM to the currently bound render target.
void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
using namespace Draw;
if (!draw_)
return;
float dstwidth = (float)PSP_CoreParameter().pixelWidth;
float dstheight = (float)PSP_CoreParameter().pixelHeight;
Viewport viewport = {0.0f, 0.0f, dstwidth, dstheight, 0.0f, 1.0f};
Draw::Viewport viewport = {0.0f, 0.0f, dstwidth, dstheight, 0.0f, 1.0f};
draw_->SetViewports(1, &viewport);
SamplerState *sampler;
if (g_Config.iBufFilter == SCALE_NEAREST) {
sampler = samplerNearest;
} else {
sampler = samplerLinear;
}
draw_->SetScissorRect(0, 0, dstwidth, dstheight);
float u0 = 0.0f;
float u1;
if (fbTex) {
fbTex->Release();
fbTex = nullptr;
}
Draw::TextureDesc desc{};
desc.type = Draw::TextureType::LINEAR2D;
desc.format = Draw::DataFormat::R8G8B8A8_UNORM;
desc.depth = 1;
desc.mipLevels = 1;
bool hasImage = true;
if (!Memory::IsValidAddress(displayFramebuf_)) {
hasImage = false;
u1 = 1.0f;
} else if (displayFormat_ == GE_FORMAT_8888) {
u8 *data = Memory::GetPointer(displayFramebuf_);
fbTex->SetImageData(0, 0, 0, displayStride_, srcheight, 1, 0, displayStride_ * 4, data);
desc.width = displayStride_;
desc.height = srcheight;
desc.initData.push_back(data);
desc.format = Draw::DataFormat::R8G8B8A8_UNORM;
u1 = (float)srcwidth / displayStride_;
} else {
// TODO: This should probably be converted in a shader instead..
@@ -201,9 +200,16 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
}
}
fbTex->SetImageData(0, 0, 0, srcwidth, srcheight, 1, 0, srcwidth * 4, (const uint8_t *)&fbTexBuffer[0]);
desc.width = srcwidth;
desc.height = srcheight;
u1 = 1.0f;
}
if (!hasImage) {
draw_->Clear(Draw::FB_COLOR_BIT, 0, 0, 0);
return;
}
fbTex = draw_->CreateTexture(desc);
float x, y, w, h;
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);
@@ -224,46 +230,48 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
x2 -= 1.0f;
y2 -= 1.0f;
if (hasImage) {
float v0 = 1.0f;
float v1 = 0.0f;
float v0 = 1.0f;
float v1 = 0.0f;
if (GetGPUBackend() == GPUBackend::VULKAN) {
std::swap(v0, v1);
}
draw_->BindSamplerStates(0, 1, &sampler);
const Vertex verts[4] = {
{ x, y, 0, u0, v0, 0xFFFFFFFF }, // TL
{ x, y2, 0, u0, v1, 0xFFFFFFFF }, // BL
{ x2, y2, 0, u1, v1, 0xFFFFFFFF }, // BR
{ x2, y, 0, u1, v0, 0xFFFFFFFF }, // TR
};
draw_->UpdateBuffer(vdata, (const uint8_t *)verts, 0, sizeof(verts), Draw::UPDATE_DISCARD);
int indexes[] = { 0, 1, 2, 0, 2, 3 };
draw_->UpdateBuffer(idata, (const uint8_t *)indexes, 0, sizeof(indexes), Draw::UPDATE_DISCARD);
draw_->BindTexture(0, fbTex);
static const float identity4x4[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
VsTexColUB ub{};
memcpy(ub.WorldViewProj, identity4x4, sizeof(float) * 16);
draw_->BindPipeline(texColor);
draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub));
draw_->BindVertexBuffers(0, 1, &vdata, nullptr);
draw_->BindIndexBuffer(idata, 0);
draw_->DrawIndexed(6, 0);
} else {
draw_->Clear(Draw::FB_COLOR_BIT, 0, 0, 0);
if (GetGPUBackend() == GPUBackend::VULKAN) {
std::swap(v0, v1);
}
Draw::SamplerState *sampler;
if (g_Config.iBufFilter == SCALE_NEAREST) {
sampler = samplerNearest;
} else {
sampler = samplerLinear;
}
draw_->BindSamplerStates(0, 1, &sampler);
const Vertex verts[4] = {
{ x, y, 0, u0, v0, 0xFFFFFFFF }, // TL
{ x, y2, 0, u0, v1, 0xFFFFFFFF }, // BL
{ x2, y2, 0, u1, v1, 0xFFFFFFFF }, // BR
{ x2, y, 0, u1, v0, 0xFFFFFFFF }, // TR
};
draw_->UpdateBuffer(vdata, (const uint8_t *)verts, 0, sizeof(verts), Draw::UPDATE_DISCARD);
int indexes[] = { 0, 1, 2, 0, 2, 3 };
draw_->UpdateBuffer(idata, (const uint8_t *)indexes, 0, sizeof(indexes), Draw::UPDATE_DISCARD);
draw_->BindTexture(0, fbTex);
static const float identity4x4[16] = {
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
Draw::VsTexColUB ub{};
memcpy(ub.WorldViewProj, identity4x4, sizeof(float) * 16);
draw_->BindPipeline(texColor);
draw_->UpdateDynamicUniformBuffer(&ub, sizeof(ub));
draw_->BindVertexBuffers(0, 1, &vdata, nullptr);
draw_->BindIndexBuffer(idata, 0);
draw_->DrawIndexed(6, 0);
}
void SoftGPU::CopyDisplayToOutput()
+2 -2
View File
@@ -122,7 +122,7 @@ public:
protected:
void Bind2DShader() override;
void BindPostShader(const PostShaderUniforms &uniforms) override;
void SetViewport2D(int x, int y, int w, int h);
void SetViewport2D(int x, int y, int w, int h) override;
void DisableState() override {}
void ClearBuffer(bool keepState = false) override;
void FlushBeforeCopy() override;
@@ -135,7 +135,7 @@ protected:
private:
// The returned texture does not need to be free'd, might be returned from a pool (currently single entry)
void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height);
void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override;
void DoNotifyDraw();
VkCommandBuffer AllocFrameCommandBuffer();
+1
View File
@@ -412,6 +412,7 @@ void GameSettingsScreen::CreateViews() {
CheckBox *softwareGPU = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareRendering, gr->T("Software Rendering", "Software Rendering (experimental)")));
softwareGPU->OnClick.Add([=](EventParams &e) {
settingInfo_->Show(gr->T("SoftGPU Tip", "Currently VERY slow"), e.v);
bloomHackEnable_ = !g_Config.bSoftwareRendering && (g_Config.iInternalResolution != 1);
return UI::EVENT_CONTINUE;
});
softwareGPU->OnClick.Handle(this, &GameSettingsScreen::OnSoftwareRendering);
+3 -5
View File
@@ -476,12 +476,11 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
TextureDesc desc{};
desc.type = TextureType::LINEAR2D;
desc.format = Draw::DataFormat::R4G4B4A4_UNORM_PACK16;
desc.format = Draw::DataFormat::B4G4R4A4_UNORM_PACK16;
desc.width = entry->bmWidth;
desc.height = entry->bmHeight;
desc.depth = 1;
desc.mipLevels = 1;
entry->texture = draw_->CreateTexture(desc);
uint16_t *bitmapData = new uint16_t[entry->bmWidth * entry->bmHeight];
for (int x = 0; x < entry->bmWidth; x++) {
@@ -489,10 +488,9 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
bitmapData[entry->bmWidth * y + x] = 0xfff0 | image.pixel(x, y) >> 28;
}
}
entry->texture->SetImageData(0, 0, 0, entry->bmWidth, entry->bmHeight, 1, 0, entry->bmWidth * 2, (const uint8_t *)bitmapData);
desc.initData.push_back((uint8_t *)bitmapData);
entry->texture = draw_->CreateTexture(desc);
delete [] bitmapData;
cache_[entryHash] = std::unique_ptr<TextStringEntry>(entry);
}
float w = entry->bmWidth * fontScaleX_;
+3 -5
View File
@@ -111,8 +111,8 @@ enum class StencilOp {
};
enum class TextureFilter : int {
NEAREST,
LINEAR,
NEAREST = 0,
LINEAR = 1,
};
enum BufferUsageFlag : int {
@@ -273,7 +273,7 @@ enum {
};
enum class TextureAddressMode {
REPEAT,
REPEAT = 0,
REPEAT_MIRROR,
CLAMP_TO_EDGE,
CLAMP_TO_BORDER,
@@ -406,8 +406,6 @@ public:
class Texture : public RefCountedObject {
public:
virtual void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) = 0;
int Width() { return width_; }
int Height() { return height_; }
int Depth() { return depth_; }
-4
View File
@@ -647,10 +647,6 @@ public:
view->Release();
}
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) {
ELOG("SetImageData not supported, create a new texture instead");
}
ID3D11Texture2D *tex = nullptr;
ID3D11ShaderResourceView *view = nullptr;
};
+2 -2
View File
@@ -297,10 +297,10 @@ class D3D9Texture : public Texture {
public:
D3D9Texture(LPDIRECT3DDEVICE9 device, LPDIRECT3DDEVICE9EX deviceEx, const TextureDesc &desc);
~D3D9Texture();
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
void SetToSampler(LPDIRECT3DDEVICE9 device, int sampler);
private:
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data);
bool Create(const TextureDesc &desc);
LPDIRECT3DDEVICE9 device_;
LPDIRECT3DDEVICE9EX deviceEx_;
@@ -364,7 +364,7 @@ bool D3D9Texture::Create(const TextureDesc &desc) {
if (desc.initData.size()) {
for (int i = 0; i < desc.initData.size(); i++) {
this->SetImageData(0, 0, 0, width_, height_, depth_, i, 0, desc.initData[i]);
SetImageData(0, 0, 0, width_, height_, depth_, i, 0, desc.initData[i]);
}
}
return true;
+132 -113
View File
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include "base/logging.h"
@@ -77,7 +78,7 @@ static const unsigned short texWrapToGL[] = {
#if !defined(USING_GLES2)
GL_CLAMP_TO_BORDER,
#else
GL_REPEAT,
GL_CLAMP_TO_EDGE,
#endif
};
@@ -193,30 +194,12 @@ public:
class OpenGLSamplerState : public SamplerState {
public:
// Old school. Should also support using a sampler object.
GLint wrapS;
GLint wrapT;
GLint wrapU;
GLint wrapV;
GLint wrapW;
GLint magFilt;
GLint minFilt;
GLint mipMinFilt;
void Apply(bool hasMips, bool canWrap) {
if (canWrap) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT);
} else {
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, magFilt);
if (hasMips) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, mipMinFilt);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilt);
}
}
};
class OpenGLDepthStencilState : public DepthStencilState {
@@ -437,6 +420,7 @@ private:
};
class OpenGLFramebuffer;
class OpenGLTexture;
class OpenGLContext : public DrawContext {
public:
@@ -484,23 +468,12 @@ public:
void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override;
void BindSamplerStates(int start, int count, SamplerState **states) override {
if (samplerStates_.size() < (size_t)(start + count)) {
samplerStates_.resize(start + count);
if (boundSamplers_.size() < (size_t)(start + count)) {
boundSamplers_.resize(start + count);
}
for (int i = 0; i < count; ++i) {
for (int i = 0; i < count; i++) {
int index = i + start;
OpenGLSamplerState *s = static_cast<OpenGLSamplerState *>(states[index]);
if (samplerStates_[index]) {
samplerStates_[index]->Release();
}
samplerStates_[index] = s;
samplerStates_[index]->AddRef();
// TODO: Ideally, get these from the texture and apply on the right stage?
if (index == 0) {
s->Apply(false, true);
}
boundSamplers_[index] = static_cast<OpenGLSamplerState *>(states[index]);
}
}
@@ -535,7 +508,7 @@ public:
curIBufferOffset_ = offset;
}
void UpdateDynamicUniformBuffer(const void *ub, size_t size);
void UpdateDynamicUniformBuffer(const void *ub, size_t size) override;
// TODO: Add more sophisticated draws.
void Draw(int vertexCount, int offset) override;
@@ -581,13 +554,16 @@ public:
void HandleEvent(Event ev) override {}
private:
OpenGLFramebuffer *fbo_ext_create(const FramebufferDesc &desc);
void fbo_bind_fb_target(bool read, GLuint name);
GLenum fbo_get_fb_target(bool read, GLuint **cached);
void fbo_unbind();
void ApplySamplers();
private:
std::vector<OpenGLSamplerState *> samplerStates_;
std::vector<OpenGLSamplerState *> boundSamplers_;
OpenGLTexture *boundTextures_[8]{};
int maxTextures_ = 0;
DeviceCaps caps_;
// Bound state
@@ -619,12 +595,7 @@ OpenGLContext::OpenGLContext() {
}
OpenGLContext::~OpenGLContext() {
for (OpenGLSamplerState *s : samplerStates_) {
if (s) {
s->Release();
}
}
samplerStates_.clear();
boundSamplers_.clear();
}
InputLayout *OpenGLContext::CreateInputLayout(const InputLayoutDesc &desc) {
@@ -646,7 +617,9 @@ GLuint TypeToTarget(TextureType type) {
case TextureType::ARRAY1D: return GL_TEXTURE_1D_ARRAY;
#endif
case TextureType::ARRAY2D: return GL_TEXTURE_2D_ARRAY;
default: return GL_NONE;
default:
ELOG("Bad texture type %d", (int)type);
return GL_NONE;
}
}
@@ -656,75 +629,92 @@ inline bool isPowerOf2(int n) {
class OpenGLTexture : public Texture {
public:
OpenGLTexture(const TextureDesc &desc) : tex_(0), target_(TypeToTarget(desc.type)), format_(desc.format), mipLevels_(desc.mipLevels) {
generatedMips_ = false;
canWrap_ = true;
width_ = desc.width;
height_ = desc.height;
depth_ = desc.depth;
canWrap_ = !isPowerOf2(width_) || !isPowerOf2(height_);
OpenGLTexture(const TextureDesc &desc);
~OpenGLTexture();
glGenTextures(1, &tex_);
if (!desc.initData.size())
return;
int level = 0;
for (auto data : desc.initData) {
SetImageData(0, 0, 0, width_, height_, depth_, level, 0, data);
width_ = (width_ + 1) /2;
height_ = (height_ + 1) /2;
level++;
}
if (desc.initData.size() < desc.mipLevels)
AutoGenMipmaps();
}
~OpenGLTexture() {
Destroy();
}
void Destroy() {
if (tex_) {
glDeleteTextures(1, &tex_);
tex_ = 0;
generatedMips_ = false;
}
}
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
void AutoGenMipmaps();
bool HasMips() {
bool HasMips() const {
return mipLevels_ > 1 || generatedMips_;
}
bool CanWrap() {
bool CanWrap() const {
return canWrap_;
}
TextureType GetType() const { return type_; }
void Bind() {
glBindTexture(target_, tex_);
}
void AutoGenMipmaps();
private:
GLuint tex_;
GLuint target_;
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data);
GLuint tex_ = 0;
GLuint target_ = 0;
DataFormat format_;
TextureType type_;
int mipLevels_;
bool generatedMips_;
bool canWrap_;
};
Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) {
return new OpenGLTexture(desc);
OpenGLTexture::OpenGLTexture(const TextureDesc &desc) {
generatedMips_ = false;
canWrap_ = true;
width_ = desc.width;
height_ = desc.height;
depth_ = desc.depth;
format_ = desc.format;
type_ = desc.type;
target_ = TypeToTarget(desc.type);
canWrap_ = isPowerOf2(width_) && isPowerOf2(height_);
if (!desc.initData.size())
return;
glActiveTexture(GL_TEXTURE0 + 0);
glGenTextures(1, &tex_);
glBindTexture(target_, tex_);
int level = 0;
for (auto data : desc.initData) {
SetImageData(0, 0, 0, width_, height_, depth_, level, 0, data);
width_ = (width_ + 1) / 2;
height_ = (height_ + 1) / 2;
level++;
}
mipLevels_ = level;
#ifdef USING_GLES2
if (gl_extensions.GLES3) {
glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, level - 1);
}
#else
glTexParameteri(target_, GL_TEXTURE_MAX_LEVEL, level - 1);
#endif
glTexParameteri(target_, GL_TEXTURE_MIN_FILTER, level > 1 ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR);
glTexParameteri(target_, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if (desc.initData.size() < desc.mipLevels) {
ILOG("Generating mipmaps");
AutoGenMipmaps();
}
// Unbind.
glBindTexture(target_, 0);
}
OpenGLTexture::~OpenGLTexture() {
if (tex_) {
glDeleteTextures(1, &tex_);
tex_ = 0;
generatedMips_ = false;
}
}
void OpenGLTexture::AutoGenMipmaps() {
if (!generatedMips_) {
Bind();
glBindTexture(target_, tex_);
glGenerateMipmap(target_);
// TODO: Really, this should follow the sampler state.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
generatedMips_ = true;
}
}
@@ -747,12 +737,11 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
format = GL_RGBA;
type = GL_UNSIGNED_BYTE;
break;
case DataFormat::R4G4B4A4_UNORM_PACK16:
case DataFormat::B4G4R4A4_UNORM_PACK16:
internalFormat = GL_RGBA;
format = GL_RGBA;
type = GL_UNSIGNED_SHORT_4_4_4_4;
break;
#ifndef USING_GLES2
case DataFormat::A4B4G4R4_UNORM_PACK16:
internalFormat = GL_RGBA;
@@ -760,18 +749,11 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
break;
#endif
default:
ELOG("Thin3d GL: Unsupported texture format %d", (int)format_);
return;
}
/*
GLenum err = glGetError();
if (err) {
ELOG("Thin3D GL: Error before loading texture: %08x", err);
}*/
Bind();
switch (target_) {
case GL_TEXTURE_2D:
glTexImage2D(GL_TEXTURE_2D, level, internalFormat, width_, height_, 0, format, type, data);
@@ -787,6 +769,10 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
}
}
Texture *OpenGLContext::CreateTexture(const TextureDesc &desc) {
return new OpenGLTexture(desc);
}
OpenGLInputLayout::~OpenGLInputLayout() {
if (id_) {
glDeleteVertexArrays(1, &id_);
@@ -852,8 +838,9 @@ BlendState *OpenGLContext::CreateBlendState(const BlendStateDesc &desc) {
SamplerState *OpenGLContext::CreateSamplerState(const SamplerStateDesc &desc) {
OpenGLSamplerState *samps = new OpenGLSamplerState();
samps->wrapS = texWrapToGL[(int)desc.wrapU];
samps->wrapT = texWrapToGL[(int)desc.wrapV];
samps->wrapU = texWrapToGL[(int)desc.wrapU];
samps->wrapV = texWrapToGL[(int)desc.wrapV];
samps->wrapW = texWrapToGL[(int)desc.wrapW];
samps->magFilt = texFilterToGL[(int)desc.magFilter];
samps->minFilt = texFilterToGL[(int)desc.minFilter];
samps->mipMinFilt = texMipFilterToGL[(int)desc.minFilter][(int)desc.mipFilter];
@@ -980,22 +967,49 @@ Pipeline *OpenGLContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
}
void OpenGLContext::BindTextures(int start, int count, Texture **textures) {
maxTextures_ = std::max(maxTextures_, start + count);
for (int i = start; i < start + count; i++) {
OpenGLTexture *glTex = static_cast<OpenGLTexture *>(textures[i]);
glActiveTexture(GL_TEXTURE0 + i);
if (!glTex) {
boundTextures_[i] = 0;
glBindTexture(GL_TEXTURE_2D, 0);
continue;
}
glTex->Bind();
if ((int)samplerStates_.size() > i && samplerStates_[i]) {
samplerStates_[i]->Apply(glTex->HasMips(), glTex->CanWrap());
}
boundTextures_[i] = glTex;
}
glActiveTexture(GL_TEXTURE0);
}
void OpenGLContext::ApplySamplers() {
for (int i = 0; i < maxTextures_; i++) {
if ((int)boundSamplers_.size() > i && boundSamplers_[i]) {
const OpenGLSamplerState *samp = boundSamplers_[i];
const OpenGLTexture *tex = boundTextures_[i];
if (!tex)
continue;
if (tex->CanWrap()) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, samp->wrapU);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, samp->wrapV);
#ifndef USING_GLES2
if (tex->GetType() == TextureType::LINEAR3D)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, samp->wrapW);
#endif
} else {
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, samp->magFilt);
if (tex->HasMips()) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, samp->mipMinFilt);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, samp->minFilt);
}
}
}
}
ShaderModule *OpenGLContext::CreateShaderModule(ShaderStage stage, ShaderLanguage language, const uint8_t *data, size_t dataSize) {
OpenGLShaderModule *shader = new OpenGLShaderModule(stage);
@@ -1102,6 +1116,7 @@ void OpenGLContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
void OpenGLContext::Draw(int vertexCount, int offset) {
curVBuffers_[0]->Bind(curVBufferOffsets_[0]);
curPipeline_->inputLayout->Apply();
ApplySamplers();
glDrawArrays(curPipeline_->prim, offset, vertexCount);
@@ -1111,6 +1126,7 @@ void OpenGLContext::Draw(int vertexCount, int offset) {
void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
curVBuffers_[0]->Bind(curVBufferOffsets_[0]);
curPipeline_->inputLayout->Apply();
ApplySamplers();
// Note: ibuf binding is stored in the VAO, so call this after binding the fmt.
curIBuffer_->Bind(curIBufferOffset_);
@@ -1121,6 +1137,7 @@ void OpenGLContext::DrawIndexed(int vertexCount, int offset) {
void OpenGLContext::DrawUP(const void *vdata, int vertexCount) {
curPipeline_->inputLayout->Apply(vdata);
ApplySamplers();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
@@ -1639,12 +1656,14 @@ uint32_t OpenGLContext::GetDataFormatSupport(DataFormat fmt) const {
switch (fmt) {
case DataFormat::B8G8R8A8_UNORM:
return FMT_RENDERTARGET | FMT_TEXTURE;
case DataFormat::R4G4B4A4_UNORM_PACK16:
return FMT_RENDERTARGET | FMT_TEXTURE;
case DataFormat::B4G4R4A4_UNORM_PACK16:
return 0; // native support
return FMT_RENDERTARGET | FMT_TEXTURE; // native support
case DataFormat::A4B4G4R4_UNORM_PACK16:
return 0; // Can support this if _REV formats are supported.
#ifndef USING_GLES2
// Can support this if _REV formats are supported.
return FMT_TEXTURE;
#endif
return 0;
case DataFormat::R8G8B8A8_UNORM:
return FMT_RENDERTARGET | FMT_TEXTURE | FMT_INPUTLAYOUT;
+2 -2
View File
@@ -597,11 +597,11 @@ public:
Destroy();
}
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data) override;
VkImageView GetImageView() { return vkTex_->GetImageView(); }
private:
void SetImageData(int x, int y, int z, int width, int height, int depth, int level, int stride, const uint8_t *data);
bool Create(const TextureDesc &desc) {
format_ = desc.format;
mipLevels_ = desc.mipLevels;