thin3d: Add sampler state selection.

This commit is contained in:
Unknown W. Brackets
2016-02-13 14:03:43 -08:00
parent 0d68a172a9
commit 05fee24ccf
7 changed files with 192 additions and 26 deletions
+7 -3
View File
@@ -131,6 +131,13 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
thin3d->SetViewports(1, &viewport);
thin3d->SetBlendState(thin3d->GetBlendStatePreset(BS_OFF));
Thin3DSamplerState *sampler;
if (g_Config.iBufFilter == SCALE_NEAREST) {
sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_NEAREST);
} else {
sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_LINEAR);
}
thin3d->SetSamplerStates(0, 1, &sampler);
thin3d->SetDepthStencilState(depth);
thin3d->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
thin3d->SetScissorEnabled(false);
@@ -177,9 +184,6 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
}
fbTex->Finalize(0);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR);
//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR);
float x, y, w, h;
CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);
+6
View File
@@ -94,6 +94,12 @@ void Thin3DContext::CreatePresets() {
bsPresets_[BS_STANDARD_ALPHA] = CreateBlendState(standard_alpha);
bsPresets_[BS_PREMUL_ALPHA] = CreateBlendState(premul_alpha);
T3DSamplerStateDesc nearest = { CLAMP, CLAMP, NEAREST, NEAREST, NEAREST };
T3DSamplerStateDesc linear = { CLAMP, CLAMP, LINEAR, LINEAR, NEAREST };
sampsPresets_[SAMPS_NEAREST] = CreateSamplerState(nearest);
sampsPresets_[SAMPS_LINEAR] = CreateSamplerState(linear);
vsPresets_[VS_TEXTURE_COLOR_2D] = CreateVertexShader(glsl_vsTexCol, hlslVsTexCol);
vsPresets_[VS_COLOR_2D] = CreateVertexShader(glsl_vsCol, hlslVsCol);
+32
View File
@@ -66,6 +66,16 @@ enum T3DBlendFactor : int {
FIXED_COLOR,
};
enum T3DTextureWrap : int {
REPEAT,
CLAMP,
};
enum T3DTextureFilter : int {
NEAREST,
LINEAR,
};
enum T3DBufferUsage : int {
VERTEXDATA = 1,
INDEXDATA = 2,
@@ -126,6 +136,12 @@ enum T3DBlendStatePreset : int {
BS_MAX_PRESET,
};
enum T3DSamplerStatePreset : int {
SAMPS_NEAREST,
SAMPS_LINEAR,
SAMPS_MAX_PRESET,
};
enum T3DClear : int {
COLOR = 1,
DEPTH = 2,
@@ -207,6 +223,10 @@ class Thin3DBlendState : public Thin3DObject {
public:
};
class Thin3DSamplerState : public Thin3DObject {
public:
};
class Thin3DDepthStencilState : public Thin3DObject {
public:
};
@@ -278,12 +298,21 @@ struct T3DBlendStateDesc {
// int colorMask;
};
struct T3DSamplerStateDesc {
T3DTextureWrap wrapS;
T3DTextureWrap wrapT;
T3DTextureFilter magFilt;
T3DTextureFilter minFilt;
T3DTextureFilter mipFilt;
};
class Thin3DContext : public Thin3DObject {
public:
virtual ~Thin3DContext();
virtual Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) = 0;
virtual Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) = 0;
virtual Thin3DSamplerState *CreateSamplerState(const T3DSamplerStateDesc &desc) = 0;
virtual Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) = 0;
virtual Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) = 0;
virtual Thin3DVertexFormat *CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) = 0;
@@ -297,6 +326,7 @@ public:
// Note that these DO NOT AddRef so you must not ->Release presets unless you manually AddRef them.
Thin3DBlendState *GetBlendStatePreset(T3DBlendStatePreset preset) { return bsPresets_[preset]; }
Thin3DSamplerState *GetSamplerStatePreset(T3DSamplerStatePreset preset) { return sampsPresets_[preset]; }
Thin3DShader *GetVshaderPreset(T3DVertexShaderPreset preset) { return fsPresets_[preset]; }
Thin3DShader *GetFshaderPreset(T3DFragmentShaderPreset preset) { return vsPresets_[preset]; }
Thin3DShaderSet *GetShaderSetPreset(T3DShaderSetPreset preset) { return ssPresets_[preset]; }
@@ -307,6 +337,7 @@ public:
// Bound state objects. Too cumbersome to add them all as parameters to Draw.
virtual void SetBlendState(Thin3DBlendState *state) = 0;
virtual void SetSamplerStates(int start, int count, Thin3DSamplerState **state) = 0;
virtual void SetDepthStencilState(Thin3DDepthStencilState *state) = 0;
virtual void SetTextures(int start, int count, Thin3DTexture **textures) = 0;
@@ -343,6 +374,7 @@ protected:
Thin3DShader *fsPresets_[FS_MAX_PRESET];
Thin3DBlendState *bsPresets_[BS_MAX_PRESET];
Thin3DShaderSet *ssPresets_[SS_MAX_PRESET];
Thin3DSamplerState *sampsPresets_[SAMPS_MAX_PRESET];
int targetWidth_;
int targetHeight_;
+41 -12
View File
@@ -56,6 +56,16 @@ static const D3DBLEND blendFactorToD3D9[] = {
D3DBLEND_BLENDFACTOR,
};
static const D3DTEXTUREADDRESS texWrapToD3D9[] = {
D3DTADDRESS_WRAP,
D3DTADDRESS_CLAMP,
};
static const D3DTEXTUREFILTERTYPE texFilterToD3D9[] = {
D3DTEXF_POINT,
D3DTEXF_LINEAR,
};
static const D3DPRIMITIVETYPE primToD3D9[] = {
D3DPT_POINTLIST,
D3DPT_LINELIST,
@@ -100,6 +110,20 @@ public:
}
};
class Thin3DDX9SamplerState : public Thin3DSamplerState {
public:
D3DTEXTUREADDRESS wrapS, wrapT;
D3DTEXTUREFILTERTYPE magFilt, minFilt, mipFilt;
void Apply(LPDIRECT3DDEVICE9 device, int index) {
device->SetSamplerState(index, D3DSAMP_ADDRESSU, wrapS);
device->SetSamplerState(index, D3DSAMP_ADDRESSV, wrapT);
device->SetSamplerState(index, D3DSAMP_MAGFILTER, magFilt);
device->SetSamplerState(index, D3DSAMP_MINFILTER, minFilt);
device->SetSamplerState(index, D3DSAMP_MIPFILTER, mipFilt);
}
};
class Thin3DDX9Buffer : public Thin3DBuffer {
public:
Thin3DDX9Buffer(LPDIRECT3DDEVICE9 device, size_t size, uint32_t flags) : vbuffer_(nullptr), ibuffer_(nullptr), maxSize_(size) {
@@ -403,6 +427,7 @@ public:
Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare);
Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override;
Thin3DSamplerState *CreateSamplerState(const T3DSamplerStateDesc &desc) override;
Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override;
Thin3DVertexFormat *CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) override;
@@ -417,6 +442,12 @@ public:
Thin3DDX9BlendState *bs = static_cast<Thin3DDX9BlendState *>(state);
bs->Apply(device_);
}
void SetSamplerStates(int start, int count, Thin3DSamplerState **states) {
for (int i = 0; i < count; ++i) {
Thin3DDX9SamplerState *s = static_cast<Thin3DDX9SamplerState *>(states[start + i]);
s->Apply(device_, start + i);
}
}
void SetDepthStencilState(Thin3DDepthStencilState *state) {
Thin3DDX9DepthStencilState *bs = static_cast<Thin3DDX9DepthStencilState *>(state);
bs->Apply(device_);
@@ -528,6 +559,16 @@ Thin3DBlendState *Thin3DDX9Context::CreateBlendState(const T3DBlendStateDesc &de
return bs;
}
Thin3DSamplerState *Thin3DDX9Context::CreateSamplerState(const T3DSamplerStateDesc &desc) {
Thin3DDX9SamplerState *samps = new Thin3DDX9SamplerState();
samps->wrapS = texWrapToD3D9[desc.wrapS];
samps->wrapT = texWrapToD3D9[desc.wrapT];
samps->magFilt = texFilterToD3D9[desc.magFilt];
samps->minFilt = texFilterToD3D9[desc.minFilt];
samps->mipFilt = texFilterToD3D9[desc.mipFilt];
return samps;
}
Thin3DTexture *Thin3DDX9Context::CreateTexture() {
Thin3DDX9Texture *tex = new Thin3DDX9Texture(device_, deviceEx_);
return tex;
@@ -631,12 +672,6 @@ void Thin3DDX9Context::Draw(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thin3
Thin3DDX9VertexFormat *fmt = static_cast<Thin3DDX9VertexFormat *>(format);
Thin3DDX9ShaderSet *ss = static_cast<Thin3DDX9ShaderSet*>(shaderSet);
device_->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
device_->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
vbuf->BindAsVertexBuf(device_, fmt->GetStride(), offset);
ss->Apply(device_);
fmt->Apply(device_);
@@ -660,12 +695,6 @@ void Thin3DDX9Context::DrawUP(T3DPrimitive prim, Thin3DShaderSet *shaderSet, Thi
Thin3DDX9VertexFormat *fmt = static_cast<Thin3DDX9VertexFormat *>(format);
Thin3DDX9ShaderSet *ss = static_cast<Thin3DDX9ShaderSet*>(shaderSet);
device_->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
device_->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
device_->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
device_->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device_->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
ss->Apply(device_);
fmt->Apply(device_);
device_->DrawPrimitiveUP(primToD3D9[prim], vertexCount / 3, vdata, fmt->GetStride());
+101 -11
View File
@@ -42,6 +42,23 @@ static const unsigned short blendFactorToGL[] = {
GL_CONSTANT_COLOR,
};
static const unsigned short texWrapToGL[] = {
GL_REPEAT,
GL_CLAMP_TO_EDGE,
};
static const unsigned short texFilterToGL[] = {
GL_NEAREST,
GL_LINEAR,
};
static const unsigned short texMipFilterToGL[2][2] = {
// Min nearest:
{ GL_NEAREST_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR },
// Min linear:
{ GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR },
};
#ifndef USING_GLES2
static const unsigned short logicOpToGL[] = {
GL_CLEAR,
@@ -114,6 +131,32 @@ public:
}
};
class Thin3DGLSamplerState : public Thin3DSamplerState {
public:
GLint wrapS;
GLint wrapT;
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 Thin3DGLDepthStencilState : public Thin3DDepthStencilState {
public:
bool depthTestEnabled;
@@ -307,6 +350,7 @@ public:
Thin3DDepthStencilState *CreateDepthStencilState(bool depthTestEnabled, bool depthWriteEnabled, T3DComparison depthCompare) override;
Thin3DBlendState *CreateBlendState(const T3DBlendStateDesc &desc) override;
Thin3DSamplerState *CreateSamplerState(const T3DSamplerStateDesc &desc) override;
Thin3DBuffer *CreateBuffer(size_t size, uint32_t usageFlags) override;
Thin3DShaderSet *CreateShaderSet(Thin3DShader *vshader, Thin3DShader *fshader) override;
Thin3DVertexFormat *CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) override;
@@ -319,6 +363,28 @@ public:
s->Apply();
}
void SetSamplerStates(int start, int count, Thin3DSamplerState **states) override {
if (samplerStates_.size() < (size_t)(start + count)) {
samplerStates_.resize(start + count);
}
for (int i = 0; i < count; ++i) {
int index = i + start;
Thin3DGLSamplerState *s = static_cast<Thin3DGLSamplerState *>(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);
}
}
}
// Bound state objects
void SetDepthStencilState(Thin3DDepthStencilState *state) override {
Thin3DGLDepthStencilState *s = static_cast<Thin3DGLDepthStencilState *>(state);
@@ -391,6 +457,8 @@ public:
default: return "?";
}
}
std::vector<Thin3DGLSamplerState *> samplerStates_;
};
Thin3DGLContext::Thin3DGLContext() {
@@ -398,6 +466,12 @@ Thin3DGLContext::Thin3DGLContext() {
}
Thin3DGLContext::~Thin3DGLContext() {
for (Thin3DGLSamplerState *s : samplerStates_) {
if (s) {
s->Release();
}
}
samplerStates_.clear();
}
Thin3DVertexFormat *Thin3DGLContext::CreateVertexFormat(const std::vector<Thin3DVertexComponent> &components, int stride, Thin3DShader *vshader) {
@@ -428,6 +502,7 @@ class Thin3DGLTexture : public Thin3DTexture, GfxResourceHolder {
public:
Thin3DGLTexture() : tex_(0), target_(0) {
generatedMips_ = false;
canWrap_ = true;
width_ = 0;
height_ = 0;
depth_ = 0;
@@ -436,6 +511,7 @@ public:
}
Thin3DGLTexture(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) : tex_(0), target_(TypeToTarget(type)), format_(format), mipLevels_(mipLevels) {
generatedMips_ = false;
canWrap_ = true;
width_ = width;
height_ = height;
depth_ = depth;
@@ -449,6 +525,7 @@ public:
bool Create(T3DTextureType type, T3DImageFormat format, int width, int height, int depth, int mipLevels) override {
generatedMips_ = false;
canWrap_ = true;
format_ = format;
target_ = TypeToTarget(type);
mipLevels_ = mipLevels;
@@ -468,6 +545,13 @@ public:
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() override;
bool HasMips() {
return mipLevels_ > 1 || generatedMips_;
}
bool CanWrap() {
return canWrap_;
}
void Bind() {
glBindTexture(target_, tex_);
}
@@ -494,6 +578,7 @@ private:
T3DImageFormat format_;
int mipLevels_;
bool generatedMips_;
bool canWrap_;
};
Thin3DTexture *Thin3DGLContext::CreateTexture() {
@@ -508,6 +593,7 @@ void Thin3DGLTexture::AutoGenMipmaps() {
if (!generatedMips_) {
Bind();
glGenerateMipmap(target_);
// TODO: Really, this should follow the sampler state.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
generatedMips_ = true;
}
@@ -553,17 +639,7 @@ bool isPowerOf2(int n) {
}
void Thin3DGLTexture::Finalize(int zim_flags) {
GLenum wrap = GL_REPEAT;
if ((zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_))
wrap = GL_CLAMP_TO_EDGE;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
if ((zim_flags & (ZIM_HAS_MIPS | ZIM_GEN_MIPS))) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
}
canWrap_ = (zim_flags & ZIM_CLAMP) || !isPowerOf2(width_) || !isPowerOf2(height_);
}
@@ -618,6 +694,16 @@ Thin3DBlendState *Thin3DGLContext::CreateBlendState(const T3DBlendStateDesc &des
return bs;
}
Thin3DSamplerState *Thin3DGLContext::CreateSamplerState(const T3DSamplerStateDesc &desc) {
Thin3DGLSamplerState *samps = new Thin3DGLSamplerState();
samps->wrapS = texWrapToGL[desc.wrapS];
samps->wrapT = texWrapToGL[desc.wrapT];
samps->magFilt = texFilterToGL[desc.magFilt];
samps->minFilt = texFilterToGL[desc.minFilt];
samps->mipMinFilt = texMipFilterToGL[desc.minFilt][desc.mipFilt];
return samps;
}
Thin3DBuffer *Thin3DGLContext::CreateBuffer(size_t size, uint32_t usageFlags) {
return new Thin3DGLBuffer(size, usageFlags);
}
@@ -645,6 +731,10 @@ void Thin3DGLContext::SetTextures(int start, int count, Thin3DTexture **textures
Thin3DGLTexture *glTex = static_cast<Thin3DGLTexture *>(textures[i]);
glActiveTexture(GL_TEXTURE0 + i);
glTex->Bind();
if (samplerStates_.size() > i && samplerStates_[i]) {
samplerStates_[i]->Apply(glTex->HasMips(), glTex->CanWrap());
}
}
glActiveTexture(GL_TEXTURE0);
}
+3
View File
@@ -23,6 +23,7 @@ UIContext::~UIContext() {
void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DShaderSet *uishadernotex, Thin3DTexture *uitexture, DrawBuffer *uidrawbuffer, DrawBuffer *uidrawbufferTop) {
thin3d_ = thin3d;
blend_ = thin3d_->GetBlendStatePreset(T3DBlendStatePreset::BS_STANDARD_ALPHA);
sampler_ = thin3d_->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_LINEAR);
depth_ = thin3d_->CreateDepthStencilState(false, false, T3DComparison::LESS);
uishader_ = uishader;
@@ -39,6 +40,7 @@ void UIContext::Init(Thin3DContext *thin3d, Thin3DShaderSet *uishader, Thin3DSha
void UIContext::Begin() {
thin3d_->SetBlendState(blend_);
thin3d_->SetSamplerStates(0, 1, &sampler_);
thin3d_->SetDepthStencilState(depth_);
thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
thin3d_->SetTexture(0, uitexture_);
@@ -48,6 +50,7 @@ void UIContext::Begin() {
void UIContext::BeginNoTex() {
thin3d_->SetBlendState(blend_);
thin3d_->SetSamplerStates(0, 1, &sampler_);
thin3d_->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
UIBegin(uishadernotex_);
+2
View File
@@ -14,6 +14,7 @@ class Thin3DShaderSet;
class Thin3DDepthStencilState;
class Thin3DTexture;
class Thin3DBlendState;
class Thin3DSamplerState;
class Texture;
class DrawBuffer;
class TextDrawer;
@@ -82,6 +83,7 @@ private:
Thin3DContext *thin3D_;
Thin3DDepthStencilState *depth_;
Thin3DBlendState *blend_;
Thin3DSamplerState *sampler_;
Thin3DShaderSet *uishader_;
Thin3DShaderSet *uishadernotex_;
Thin3DTexture *uitexture_;