Use OpenGL sampler objects

This commit is contained in:
Magnus Norddahl 2019-12-18 03:24:09 +01:00
parent b70b114a6b
commit de2e336cb1
3 changed files with 65 additions and 35 deletions

View file

@ -230,13 +230,7 @@ namespace CodeImp.DoomBuilder.Rendering
public void SetSamplerState(TextureAddress address)
{
SetSamplerState(address, address, address);
CheckAndThrow();
}
public void SetSamplerState(TextureAddress addressU, TextureAddress addressV, TextureAddress addressW)
{
RenderDevice_SetSamplerState(Handle, addressU, addressV, addressW);
RenderDevice_SetSamplerState(Handle, address);
CheckAndThrow();
}
@ -480,7 +474,7 @@ namespace CodeImp.DoomBuilder.Rendering
static extern void RenderDevice_SetSamplerFilter(IntPtr handle, TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_SetSamplerState(IntPtr handle, TextureAddress addressU, TextureAddress addressV, TextureAddress addressW);
static extern void RenderDevice_SetSamplerState(IntPtr handle, TextureAddress address);
[DllImport("BuilderNative", CallingConvention = CallingConvention.Cdecl)]
static extern void RenderDevice_Draw(IntPtr handle, PrimitiveType type, int startIndex, int primitiveCount);

View file

@ -74,6 +74,14 @@ RenderDevice::~RenderDevice()
handle = sharedbuf->GetVAO();
glDeleteVertexArrays(1, &handle);
}
for (auto& it : mSamplers)
{
for (GLuint handle : it.second.WrapModes)
{
if (handle != 0)
glDeleteSamplers(1, &handle);
}
}
mShaderManager->ReleaseResources();
Context->ClearCurrent();
}
@ -220,13 +228,15 @@ void RenderDevice::SetTexture(Texture* texture)
void RenderDevice::SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy)
{
auto glminfilter = GetGLMinFilter(minfilter, mipfilter);
auto glmagfilter = (magfilter == TextureFilter::Point || magfilter == TextureFilter::None) ? GL_NEAREST : GL_LINEAR;
if (mTextureUnit.MinFilter != glminfilter || mTextureUnit.MagFilter != glmagfilter || mTextureUnit.MaxAnisotropy != maxanisotropy)
SamplerFilterKey key;
key.MinFilter = GetGLMinFilter(minfilter, mipfilter);
key.MagFilter = (magfilter == TextureFilter::Point || magfilter == TextureFilter::None) ? GL_NEAREST : GL_LINEAR;
key.MaxAnisotropy = maxanisotropy;
if (mSamplerFilterKey != key)
{
mTextureUnit.MinFilter = glminfilter;
mTextureUnit.MagFilter = glmagfilter;
mTextureUnit.MaxAnisotropy = maxanisotropy;
mSamplerFilterKey = key;
mSamplerFilter = &mSamplers[mSamplerFilterKey];
mNeedApply = true;
mTexturesChanged = true;
}
@ -257,13 +267,11 @@ GLint RenderDevice::GetGLMinFilter(TextureFilter filter, TextureFilter mipfilter
}
}
void RenderDevice::SetSamplerState(TextureAddress addressU, TextureAddress addressV, TextureAddress addressW)
void RenderDevice::SetSamplerState(TextureAddress address)
{
if (mTextureUnit.AddressU != addressU || mTextureUnit.AddressV != addressV || mTextureUnit.AddressW != addressW)
if (mTextureUnit.WrapMode != address)
{
mTextureUnit.AddressU = addressU;
mTextureUnit.AddressV = addressV;
mTextureUnit.AddressW = addressW;
mTextureUnit.WrapMode = address;
mNeedApply = true;
mTexturesChanged = true;
}
@ -777,19 +785,31 @@ void RenderDevice::ApplyUniforms()
void RenderDevice::ApplyTextures()
{
static const int wrapMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE };
glActiveTexture(GL_TEXTURE0);
if (mTextureUnit.Tex)
{
GLenum target = mTextureUnit.Tex->IsCubeTexture() ? GL_TEXTURE_CUBE_MAP : GL_TEXTURE_2D;
glBindTexture(target, mTextureUnit.Tex->GetTexture());
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, mTextureUnit.MinFilter);
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, mTextureUnit.MagFilter);
glTexParameteri(target, GL_TEXTURE_WRAP_S, wrapMode[(int)mTextureUnit.AddressU]);
glTexParameteri(target, GL_TEXTURE_WRAP_T, wrapMode[(int)mTextureUnit.AddressV]);
glTexParameteri(target, GL_TEXTURE_WRAP_R, wrapMode[(int)mTextureUnit.AddressW]);
GLuint& samplerHandle = mSamplerFilter->WrapModes[(int)mTextureUnit.WrapMode];
if (samplerHandle == 0)
{
static const int wrapMode[] = { GL_REPEAT, GL_CLAMP_TO_EDGE };
glGenSamplers(1, &samplerHandle);
glSamplerParameteri(samplerHandle, GL_TEXTURE_MIN_FILTER, mSamplerFilterKey.MinFilter);
glSamplerParameteri(samplerHandle, GL_TEXTURE_MAG_FILTER, mSamplerFilterKey.MagFilter);
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_S, wrapMode[(int)mTextureUnit.WrapMode]);
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_T, wrapMode[(int)mTextureUnit.WrapMode]);
glSamplerParameteri(samplerHandle, GL_TEXTURE_WRAP_R, wrapMode[(int)mTextureUnit.WrapMode]);
}
if (mTextureUnit.SamplerHandle != samplerHandle)
{
mTextureUnit.SamplerHandle = samplerHandle;
glBindSampler(0, samplerHandle);
}
}
else
{
@ -910,9 +930,9 @@ void RenderDevice_SetSamplerFilter(RenderDevice* device, TextureFilter minfilter
device->SetSamplerFilter(minfilter, magfilter, mipfilter, maxanisotropy);
}
void RenderDevice_SetSamplerState(RenderDevice* device, TextureAddress addressU, TextureAddress addressV, TextureAddress addressW)
void RenderDevice_SetSamplerState(RenderDevice* device, TextureAddress address)
{
device->SetSamplerState(addressU, addressV, addressW);
device->SetSamplerState(address);
}
void RenderDevice_Draw(RenderDevice* device, PrimitiveType type, int startIndex, int primitiveCount)

View file

@ -97,7 +97,7 @@ public:
void SetZWriteEnable(bool value);
void SetTexture(Texture* texture);
void SetSamplerFilter(TextureFilter minfilter, TextureFilter magfilter, TextureFilter mipfilter, float maxanisotropy);
void SetSamplerState(TextureAddress addressU, TextureAddress addressV, TextureAddress addressW);
void SetSamplerState(TextureAddress address);
void Draw(PrimitiveType type, int startIndex, int primitiveCount);
void DrawIndexed(PrimitiveType type, int startIndex, int primitiveCount);
void DrawData(PrimitiveType type, int startIndex, int primitiveCount, const void* data);
@ -142,14 +142,30 @@ public:
struct TextureUnit
{
Texture* Tex = nullptr;
GLuint MinFilter = GL_NEAREST;
GLuint MagFilter = GL_NEAREST;
float MaxAnisotropy = 0.0f;
TextureAddress AddressU = TextureAddress::Wrap;
TextureAddress AddressV = TextureAddress::Wrap;
TextureAddress AddressW = TextureAddress::Wrap;
TextureAddress WrapMode = TextureAddress::Wrap;
GLuint SamplerHandle = 0;
} mTextureUnit;
struct SamplerFilterKey
{
GLuint MinFilter = 0;
GLuint MagFilter = 0;
float MaxAnisotropy = 0.0f;
bool operator<(const SamplerFilterKey& b) const { return memcmp(this, &b, sizeof(SamplerFilterKey)) < 0; }
bool operator==(const SamplerFilterKey& b) const { return memcmp(this, &b, sizeof(SamplerFilterKey)) == 0; }
bool operator!=(const SamplerFilterKey& b) const { return memcmp(this, &b, sizeof(SamplerFilterKey)) != 0; }
};
struct SamplerFilter
{
GLuint WrapModes[2] = { 0, 0 };
};
std::map<SamplerFilterKey, SamplerFilter> mSamplers;
SamplerFilterKey mSamplerFilterKey;
SamplerFilter* mSamplerFilter = nullptr;
int mVertexBuffer = -1;
int64_t mVertexBufferStartIndex = 0;