mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-17 04:39:34 +00:00
thin3d: Make the stencil ref value dynamic state (all APIs support this directly).
This commit is contained in:
parent
df98721e73
commit
c2319cd6d1
@ -4,27 +4,39 @@
|
||||
|
||||
static const std::vector<Draw::ShaderSource> fsDiscard = {
|
||||
{Draw::ShaderLanguage::GLSL_ES_200,
|
||||
R"(varying vec4 oColor0;
|
||||
R"(
|
||||
#ifdef GL_ES
|
||||
precision lowp float;
|
||||
#endif
|
||||
#if __VERSION__ >= 130
|
||||
#define varying in
|
||||
#define gl_FragColor fragColor0
|
||||
out vec4 fragColor0;
|
||||
#endif
|
||||
varying vec4 oColor0;
|
||||
varying vec2 oTexCoord0;
|
||||
uniform sampler2D Sampler0;
|
||||
void main() {
|
||||
vec4 color = texture2D(Sampler0, oTexCoord0) * oColor0;
|
||||
if (color.a <= 0.0)
|
||||
discard;
|
||||
gl_FragColor = color;
|
||||
vec4 color = texture2D(Sampler0, oTexCoord0) * oColor0;
|
||||
if (color.a <= 0.0)
|
||||
discard;
|
||||
gl_FragColor = color;
|
||||
})"
|
||||
},
|
||||
{Draw::ShaderLanguage::GLSL_VULKAN,
|
||||
R"(layout(location = 0) in vec4 oColor0;
|
||||
R"(#version 140
|
||||
#extension GL_ARB_separate_shader_objects : enable
|
||||
#extension GL_ARB_shading_language_420pack : enable
|
||||
layout(location = 0) in vec4 oColor0;
|
||||
layout(location = 1) in vec2 oTexCoord0;
|
||||
layout(location = 0) out vec4 fragColor0;
|
||||
layout(set = 0, binding = 1) uniform sampler2D Sampler0;
|
||||
void main() {
|
||||
vec4 color = texture(Sampler0, oTexCoord0) * oColor0;
|
||||
if (color.a <= 0.0)
|
||||
discard;
|
||||
fragColor0 = color;
|
||||
})"
|
||||
vec4 color = texture(Sampler0, oTexCoord0) * oColor0;
|
||||
if (color.a <= 0.0)
|
||||
discard;
|
||||
fragColor0 = color;
|
||||
})"
|
||||
},
|
||||
};
|
||||
|
||||
@ -81,7 +93,6 @@ void GPUDriverTestScreen::render() {
|
||||
dsDesc.front.passOp = StencilOp::REPLACE;
|
||||
dsDesc.front.failOp = StencilOp::ZERO;
|
||||
dsDesc.front.depthFailOp = StencilOp::ZERO;
|
||||
dsDesc.front.reference = 0xFF;
|
||||
dsDesc.front.writeMask = 0xFF;
|
||||
dsDesc.back = dsDesc.front;
|
||||
DepthStencilState *depthStencilWrite = draw->CreateDepthStencilState(dsDesc);
|
||||
@ -129,9 +140,11 @@ void GPUDriverTestScreen::render() {
|
||||
}
|
||||
|
||||
UIContext &dc = *screenManager()->getUIContext();
|
||||
Draw::DrawContext *draw = dc.GetDrawContext();
|
||||
const Bounds &bounds = dc.GetBounds();
|
||||
|
||||
const char *testNames[] = {"Normal", "Z test", "Stencil test"};
|
||||
Pipeline *testPipelines[] = { drawTestStencil_, drawTestDepth_, drawTestStencil_ };
|
||||
|
||||
const int numTests = ARRAY_SIZE(testNames);
|
||||
|
||||
@ -152,6 +165,7 @@ void GPUDriverTestScreen::render() {
|
||||
dc.Begin();
|
||||
dc.SetFontScale(1.0f, 1.0f);
|
||||
Bounds bounds = {x - testW / 2, y + 40, testW, 70};
|
||||
draw->SetStencilRef(0x0);
|
||||
dc.DrawText(testNames[i], bounds.x, y, style.fgColor, FLAG_DYNAMIC_ASCII);
|
||||
|
||||
dc.FillRect(UI::Drawable(bgColorOK), bounds);
|
||||
|
@ -679,6 +679,8 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch
|
||||
screenManager->switchScreen(new LogoScreen());
|
||||
}
|
||||
|
||||
screenManager->push(new GPUDriverTestScreen());
|
||||
|
||||
if (g_Config.bRemoteShareOnStartup && g_Config.bRemoteDebuggerOnStartup)
|
||||
StartWebServer(WebServerFlags::ALL);
|
||||
else if (g_Config.bRemoteShareOnStartup)
|
||||
|
@ -416,7 +416,6 @@ struct StencilSide {
|
||||
Comparison compareOp;
|
||||
uint8_t compareMask;
|
||||
uint8_t writeMask;
|
||||
uint8_t reference;
|
||||
};
|
||||
|
||||
struct DepthStencilStateDesc {
|
||||
@ -588,6 +587,7 @@ public:
|
||||
virtual void SetScissorRect(int left, int top, int width, int height) = 0;
|
||||
virtual void SetViewports(int count, Viewport *viewports) = 0;
|
||||
virtual void SetBlendFactor(float color[4]) = 0;
|
||||
virtual void SetStencilRef(uint8_t ref) = 0;
|
||||
|
||||
virtual void BindSamplerStates(int start, int count, SamplerState **state) = 0;
|
||||
virtual void BindTextures(int start, int count, Texture **textures) = 0;
|
||||
|
@ -95,6 +95,10 @@ public:
|
||||
blendFactorDirty_ = true;
|
||||
}
|
||||
}
|
||||
void SetStencilRef(uint8_t ref) override {
|
||||
stencilRef_ = ref;
|
||||
stencilRefDirty_ = true;
|
||||
}
|
||||
|
||||
void Draw(int vertexCount, int offset) override;
|
||||
void DrawIndexed(int vertexCount, int offset) override;
|
||||
@ -204,8 +208,8 @@ private:
|
||||
// Dynamic state
|
||||
float blendFactor_[4]{};
|
||||
bool blendFactorDirty_ = false;
|
||||
uint8_t stencilRef_;
|
||||
bool stencilRefDirty_;
|
||||
uint8_t stencilRef_ = 0;
|
||||
bool stencilRefDirty_ = true;
|
||||
|
||||
// Temporaries
|
||||
ID3D11Texture2D *packTexture_ = nullptr;
|
||||
@ -975,7 +979,6 @@ void D3D11DrawContext::BindPipeline(Pipeline *pipeline) {
|
||||
curPipeline_ = dPipeline;
|
||||
}
|
||||
|
||||
// Gonna need dirtyflags soon..
|
||||
void D3D11DrawContext::ApplyCurrentState() {
|
||||
if (curBlend_ != curPipeline_->blend || blendFactorDirty_) {
|
||||
context_->OMSetBlendState(curPipeline_->blend->bs, blendFactor_, 0xFFFFFFFF);
|
||||
|
@ -154,7 +154,6 @@ public:
|
||||
D3DSTENCILOP stencilZFail;
|
||||
D3DSTENCILOP stencilPass;
|
||||
D3DCMPFUNC stencilCompareOp;
|
||||
uint8_t stencilReference;
|
||||
uint8_t stencilCompareMask;
|
||||
uint8_t stencilWriteMask;
|
||||
void Apply(LPDIRECT3DDEVICE9 device) {
|
||||
@ -170,7 +169,6 @@ public:
|
||||
device->SetRenderState(D3DRS_STENCILPASS, stencilPass);
|
||||
device->SetRenderState(D3DRS_STENCILFUNC, stencilCompareOp);
|
||||
device->SetRenderState(D3DRS_STENCILMASK, stencilCompareMask);
|
||||
device->SetRenderState(D3DRS_STENCILREF, stencilReference);
|
||||
device->SetRenderState(D3DRS_STENCILWRITEMASK, stencilWriteMask);
|
||||
}
|
||||
}
|
||||
@ -523,6 +521,7 @@ public:
|
||||
void SetScissorRect(int left, int top, int width, int height) override;
|
||||
void SetViewports(int count, Viewport *viewports) override;
|
||||
void SetBlendFactor(float color[4]) override;
|
||||
void SetStencilRef(uint8_t ref) override;
|
||||
|
||||
void Draw(int vertexCount, int offset) override;
|
||||
void DrawIndexed(int vertexCount, int offset) override;
|
||||
@ -684,7 +683,6 @@ DepthStencilState *D3D9Context::CreateDepthStencilState(const DepthStencilStateD
|
||||
ds->stencilFail = stencilOpToD3D9[(int)desc.front.failOp];
|
||||
ds->stencilZFail = stencilOpToD3D9[(int)desc.front.depthFailOp];
|
||||
ds->stencilWriteMask = desc.front.writeMask;
|
||||
ds->stencilReference = desc.front.reference;
|
||||
ds->stencilCompareMask = desc.front.compareMask;
|
||||
return ds;
|
||||
}
|
||||
@ -966,6 +964,10 @@ void D3D9Context::SetBlendFactor(float color[4]) {
|
||||
device_->SetRenderState(D3DRS_BLENDFACTOR, r | (g << 8) | (b << 16) | (a << 24));
|
||||
}
|
||||
|
||||
void D3D9Context::SetStencilRef(uint8_t ref) {
|
||||
device_->SetRenderState(D3DRS_STENCILREF, (DWORD)ref);
|
||||
}
|
||||
|
||||
bool D3D9ShaderModule::Compile(LPDIRECT3DDEVICE9 device, const uint8_t *data, size_t size) {
|
||||
LPD3DXMACRO defines = nullptr;
|
||||
LPD3DXINCLUDE includes = nullptr;
|
||||
|
@ -192,13 +192,12 @@ public:
|
||||
GLuint stencilZFail;
|
||||
GLuint stencilPass;
|
||||
GLuint stencilCompareOp;
|
||||
uint8_t stencilReference;
|
||||
uint8_t stencilCompareMask;
|
||||
uint8_t stencilWriteMask;
|
||||
|
||||
void Apply(GLRenderManager *render) {
|
||||
void Apply(GLRenderManager *render, uint8_t stencilRef) {
|
||||
render->SetDepth(depthTestEnabled, depthWriteEnabled, depthComp);
|
||||
render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilReference, stencilCompareMask);
|
||||
render->SetStencilFunc(stencilEnabled, stencilCompareOp, stencilRef, stencilCompareMask);
|
||||
render->SetStencilOp(stencilWriteMask, stencilFail, stencilZFail, stencilPass);
|
||||
}
|
||||
};
|
||||
@ -404,6 +403,15 @@ public:
|
||||
renderManager_.SetBlendFactor(color);
|
||||
}
|
||||
|
||||
void SetStencilRef(uint8_t ref) override {
|
||||
stencilRef_ = ref;
|
||||
renderManager_.SetStencilFunc(
|
||||
curPipeline_->depthStencil->stencilEnabled,
|
||||
curPipeline_->depthStencil->stencilCompareOp,
|
||||
ref,
|
||||
curPipeline_->depthStencil->stencilCompareMask);
|
||||
}
|
||||
|
||||
void BindTextures(int start, int count, Texture **textures) override;
|
||||
void BindPipeline(Pipeline *pipeline) override;
|
||||
void BindVertexBuffers(int start, int count, Buffer **buffers, int *offsets) override {
|
||||
@ -485,6 +493,8 @@ private:
|
||||
OpenGLBuffer *curIBuffer_ = nullptr;
|
||||
int curIBufferOffset_ = 0;
|
||||
|
||||
uint8_t stencilRef_ = 0;
|
||||
|
||||
// Frames in flight is not such a strict concept as with Vulkan until we start using glBufferStorage and fences.
|
||||
// But might as well have the structure ready, and can't hurt to rotate buffers.
|
||||
struct FrameData {
|
||||
@ -750,7 +760,6 @@ DepthStencilState *OpenGLContext::CreateDepthStencilState(const DepthStencilStat
|
||||
ds->stencilFail = stencilOpToGL[(int)desc.front.failOp];
|
||||
ds->stencilZFail = stencilOpToGL[(int)desc.front.depthFailOp];
|
||||
ds->stencilWriteMask = desc.front.writeMask;
|
||||
ds->stencilReference = desc.front.reference;
|
||||
ds->stencilCompareMask = desc.front.compareMask;
|
||||
return ds;
|
||||
}
|
||||
@ -959,7 +968,7 @@ bool OpenGLPipeline::LinkShaders() {
|
||||
void OpenGLContext::BindPipeline(Pipeline *pipeline) {
|
||||
curPipeline_ = (OpenGLPipeline *)pipeline;
|
||||
curPipeline_->blend->Apply(&renderManager_);
|
||||
curPipeline_->depthStencil->Apply(&renderManager_);
|
||||
curPipeline_->depthStencil->Apply(&renderManager_, stencilRef_);
|
||||
curPipeline_->raster->Apply(&renderManager_);
|
||||
renderManager_.BindProgram(curPipeline_->program_);
|
||||
}
|
||||
|
@ -275,6 +275,10 @@ public:
|
||||
int stride[4]{};
|
||||
int dynamicUniformSize = 0;
|
||||
|
||||
bool usesStencil = false;
|
||||
uint8_t stencilWriteMask = 0xFF;
|
||||
uint8_t stencilTestMask = 0xFF;
|
||||
|
||||
private:
|
||||
VulkanContext *vulkan_;
|
||||
uint8_t *ubo_;
|
||||
@ -388,6 +392,7 @@ public:
|
||||
void SetScissorRect(int left, int top, int width, int height) override;
|
||||
void SetViewports(int count, Viewport *viewports) override;
|
||||
void SetBlendFactor(float color[4]) override;
|
||||
void SetStencilRef(uint8_t stencilRef) override;
|
||||
|
||||
void BindSamplerStates(int start, int count, SamplerState **state) override;
|
||||
void BindTextures(int start, int count, Texture **textures) override;
|
||||
@ -414,6 +419,8 @@ public:
|
||||
void DrawIndexed(int vertexCount, int offset) override;
|
||||
void DrawUP(const void *vdata, int vertexCount) override;
|
||||
|
||||
void ApplyDynamicState();
|
||||
|
||||
void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) override;
|
||||
|
||||
void BeginFrame() override;
|
||||
@ -541,6 +548,8 @@ private:
|
||||
VulkanPushBuffer *push_ = nullptr;
|
||||
|
||||
DeviceCaps caps_{};
|
||||
|
||||
uint8_t stencilRef_ = 0;
|
||||
};
|
||||
|
||||
static int GetBpp(VkFormat format) {
|
||||
@ -979,9 +988,10 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
|
||||
inputAssembly.topology = primToVK[(int)desc.prim];
|
||||
inputAssembly.primitiveRestartEnable = false;
|
||||
|
||||
VkDynamicState dynamics[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
|
||||
// We treat the three stencil states as a unit in other places, so let's do that here too.
|
||||
VkDynamicState dynamics[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK, VK_DYNAMIC_STATE_STENCIL_REFERENCE, VK_DYNAMIC_STATE_STENCIL_WRITE_MASK };
|
||||
VkPipelineDynamicStateCreateInfo dynamicInfo = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO };
|
||||
dynamicInfo.dynamicStateCount = ARRAY_SIZE(dynamics);
|
||||
dynamicInfo.dynamicStateCount = depth->info.stencilTestEnable ? ARRAY_SIZE(dynamics) : 2;
|
||||
dynamicInfo.pDynamicStates = dynamics;
|
||||
|
||||
VkPipelineMultisampleStateCreateInfo ms = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO };
|
||||
@ -1027,7 +1037,11 @@ Pipeline *VKContext::CreateGraphicsPipeline(const PipelineDesc &desc) {
|
||||
if (desc.uniformDesc) {
|
||||
pipeline->dynamicUniformSize = (int)desc.uniformDesc->uniformBufferSize;
|
||||
}
|
||||
|
||||
if (depth->info.stencilTestEnable) {
|
||||
pipeline->usesStencil = true;
|
||||
pipeline->stencilTestMask = depth->info.front.compareMask;
|
||||
pipeline->stencilWriteMask = depth->info.front.writeMask;
|
||||
}
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
@ -1053,6 +1067,12 @@ void VKContext::SetBlendFactor(float color[4]) {
|
||||
renderManager_.SetBlendFactor(color);
|
||||
}
|
||||
|
||||
void VKContext::SetStencilRef(uint8_t stencilRef) {
|
||||
if (curPipeline_->usesStencil)
|
||||
renderManager_.SetStencilParams(curPipeline_->stencilWriteMask, curPipeline_->stencilTestMask, stencilRef);
|
||||
stencilRef_ = stencilRef;
|
||||
}
|
||||
|
||||
InputLayout *VKContext::CreateInputLayout(const InputLayoutDesc &desc) {
|
||||
VKInputLayout *vl = new VKInputLayout();
|
||||
vl->visc = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO };
|
||||
@ -1096,7 +1116,6 @@ Texture *VKContext::CreateTexture(const TextureDesc &desc) {
|
||||
|
||||
static inline void CopySide(VkStencilOpState &dest, const StencilSide &src) {
|
||||
dest.compareMask = src.compareMask;
|
||||
dest.reference = src.reference;
|
||||
dest.writeMask = src.writeMask;
|
||||
dest.compareOp = compToVK[(int)src.compareOp];
|
||||
dest.failOp = stencilOpToVK[(int)src.failOp];
|
||||
@ -1109,7 +1128,7 @@ DepthStencilState *VKContext::CreateDepthStencilState(const DepthStencilStateDes
|
||||
ds->info.depthCompareOp = compToVK[(int)desc.depthCompare];
|
||||
ds->info.depthTestEnable = desc.depthTestEnabled;
|
||||
ds->info.depthWriteEnable = desc.depthWriteEnabled;
|
||||
ds->info.stencilTestEnable = false;
|
||||
ds->info.stencilTestEnable = desc.stencilEnabled;
|
||||
ds->info.depthBoundsTestEnable = false;
|
||||
if (ds->info.stencilTestEnable) {
|
||||
CopySide(ds->info.front, desc.front);
|
||||
@ -1197,6 +1216,13 @@ void VKContext::UpdateDynamicUniformBuffer(const void *ub, size_t size) {
|
||||
curPipeline_->SetDynamicUniformData(ub, size);
|
||||
}
|
||||
|
||||
void VKContext::ApplyDynamicState() {
|
||||
// TODO: blend constants, stencil, viewports should be here, after bindpipeline..
|
||||
if (curPipeline_->usesStencil) {
|
||||
renderManager_.SetStencilParams(curPipeline_->stencilWriteMask, curPipeline_->stencilTestMask, stencilRef_);
|
||||
}
|
||||
}
|
||||
|
||||
void VKContext::Draw(int vertexCount, int offset) {
|
||||
VKBuffer *vbuf = curVBuffers_[0];
|
||||
|
||||
@ -1208,7 +1234,7 @@ void VKContext::Draw(int vertexCount, int offset) {
|
||||
VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
|
||||
|
||||
renderManager_.BindPipeline(curPipeline_->vkpipeline);
|
||||
// TODO: blend constants, stencil, viewports should be here, after bindpipeline..
|
||||
ApplyDynamicState();
|
||||
renderManager_.Draw(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vertexCount);
|
||||
}
|
||||
|
||||
@ -1224,7 +1250,7 @@ void VKContext::DrawIndexed(int vertexCount, int offset) {
|
||||
VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
|
||||
|
||||
renderManager_.BindPipeline(curPipeline_->vkpipeline);
|
||||
// TODO: blend constants, stencil, viewports should be here, after bindpipeline..
|
||||
ApplyDynamicState();
|
||||
renderManager_.DrawIndexed(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vulkanIbuf, (int)ibBindOffset, vertexCount, 1, VK_INDEX_TYPE_UINT32);
|
||||
}
|
||||
|
||||
@ -1236,7 +1262,7 @@ void VKContext::DrawUP(const void *vdata, int vertexCount) {
|
||||
VkDescriptorSet descSet = GetOrCreateDescriptorSet(vulkanUBObuf);
|
||||
|
||||
renderManager_.BindPipeline(curPipeline_->vkpipeline);
|
||||
// TODO: blend constants, stencil, viewports should be here, after bindpipeline..
|
||||
ApplyDynamicState();
|
||||
renderManager_.Draw(pipelineLayout_, descSet, 1, &ubo_offset, vulkanVbuf, (int)vbBindOffset, vertexCount);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user