mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-02-10 09:41:13 +00:00
- add stencil buffer support for 2d drawing (#1660)
Co-authored-by: Christoph Oelckers <coelckers@users.noreply.github.com>
This commit is contained in:
parent
1e27fac288
commit
ee0d90a983
13 changed files with 224 additions and 17 deletions
|
@ -1142,6 +1142,55 @@ void F2DDrawer::AddPixel(int x1, int y1, uint32_t color)
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
|
void F2DDrawer::AddEnableStencil(bool on)
|
||||||
|
{
|
||||||
|
RenderCommand dg;
|
||||||
|
|
||||||
|
dg.isSpecial = SpecialDrawCommand::EnableStencil;
|
||||||
|
dg.stencilOn = on;
|
||||||
|
|
||||||
|
AddCommand(&dg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void F2DDrawer::AddSetStencil(int offs, int op, int flags)
|
||||||
|
{
|
||||||
|
RenderCommand dg;
|
||||||
|
|
||||||
|
dg.isSpecial = SpecialDrawCommand::SetStencil;
|
||||||
|
dg.stencilOffs = offs;
|
||||||
|
dg.stencilOp = op;
|
||||||
|
dg.stencilFlags = flags;
|
||||||
|
|
||||||
|
AddCommand(&dg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
|
void F2DDrawer::AddClearStencil()
|
||||||
|
{
|
||||||
|
RenderCommand dg;
|
||||||
|
|
||||||
|
dg.isSpecial = SpecialDrawCommand::ClearStencil;
|
||||||
|
|
||||||
|
AddCommand(&dg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==========================================================================
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
|
//==========================================================================
|
||||||
|
|
||||||
void F2DDrawer::Clear()
|
void F2DDrawer::Clear()
|
||||||
{
|
{
|
||||||
if (!locked)
|
if (!locked)
|
||||||
|
|
|
@ -52,6 +52,14 @@ struct F2DPolygons
|
||||||
class DShape2D;
|
class DShape2D;
|
||||||
struct DShape2DBufferInfo;
|
struct DShape2DBufferInfo;
|
||||||
|
|
||||||
|
enum class SpecialDrawCommand {
|
||||||
|
NotSpecial,
|
||||||
|
|
||||||
|
EnableStencil,
|
||||||
|
SetStencil,
|
||||||
|
ClearStencil,
|
||||||
|
};
|
||||||
|
|
||||||
class F2DDrawer
|
class F2DDrawer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -107,6 +115,14 @@ public:
|
||||||
|
|
||||||
struct RenderCommand
|
struct RenderCommand
|
||||||
{
|
{
|
||||||
|
SpecialDrawCommand isSpecial;
|
||||||
|
|
||||||
|
bool stencilOn;
|
||||||
|
|
||||||
|
int stencilOffs;
|
||||||
|
int stencilOp;
|
||||||
|
int stencilFlags;
|
||||||
|
|
||||||
EDrawType mType;
|
EDrawType mType;
|
||||||
int mVertIndex;
|
int mVertIndex;
|
||||||
int mVertCount;
|
int mVertCount;
|
||||||
|
@ -141,6 +157,10 @@ public:
|
||||||
// If these fields match, two draw commands can be batched.
|
// If these fields match, two draw commands can be batched.
|
||||||
bool isCompatible(const RenderCommand &other) const
|
bool isCompatible(const RenderCommand &other) const
|
||||||
{
|
{
|
||||||
|
if (
|
||||||
|
isSpecial != SpecialDrawCommand::NotSpecial ||
|
||||||
|
other.isSpecial != SpecialDrawCommand::NotSpecial
|
||||||
|
) return false;
|
||||||
if (shape2DBufInfo != nullptr || other.shape2DBufInfo != nullptr) return false;
|
if (shape2DBufInfo != nullptr || other.shape2DBufInfo != nullptr) return false;
|
||||||
return mTexture == other.mTexture &&
|
return mTexture == other.mTexture &&
|
||||||
mType == other.mType &&
|
mType == other.mType &&
|
||||||
|
@ -210,6 +230,10 @@ public:
|
||||||
void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255);
|
void AddThickLine(int x1, int y1, int x2, int y2, double thickness, uint32_t color, uint8_t alpha = 255);
|
||||||
void AddPixel(int x1, int y1, uint32_t color);
|
void AddPixel(int x1, int y1, uint32_t color);
|
||||||
|
|
||||||
|
void AddEnableStencil(bool on);
|
||||||
|
void AddSetStencil(int offs, int op, int flags);
|
||||||
|
void AddClearStencil();
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void Lock() { locked = true; }
|
void Lock() { locked = true; }
|
||||||
void SetScreenFade(float factor) { screenFade = factor; }
|
void SetScreenFade(float factor) { screenFade = factor; }
|
||||||
|
|
|
@ -1626,6 +1626,40 @@ DEFINE_ACTION_FUNCTION(_Screen, SetOffset)
|
||||||
ACTION_RETURN_VEC2(twod->SetOffset(DVector2(x, y)));
|
ACTION_RETURN_VEC2(twod->SetOffset(DVector2(x, y)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Screen, EnableStencil)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_BOOL(on);
|
||||||
|
|
||||||
|
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||||
|
|
||||||
|
twod->AddEnableStencil(on);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Screen, SetStencil)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
PARAM_INT(offs);
|
||||||
|
PARAM_INT(op);
|
||||||
|
PARAM_INT(flags);
|
||||||
|
|
||||||
|
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||||
|
|
||||||
|
twod->AddSetStencil(offs, op, flags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_ACTION_FUNCTION(_Screen, ClearStencil)
|
||||||
|
{
|
||||||
|
PARAM_PROLOGUE;
|
||||||
|
|
||||||
|
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||||
|
|
||||||
|
twod->AddClearStencil();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
DEFINE_ACTION_FUNCTION(_Screen, SetTransform)
|
DEFINE_ACTION_FUNCTION(_Screen, SetTransform)
|
||||||
{
|
{
|
||||||
PARAM_PROLOGUE;
|
PARAM_PROLOGUE;
|
||||||
|
@ -1645,6 +1679,5 @@ DEFINE_ACTION_FUNCTION(_Screen, ClearTransform)
|
||||||
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function");
|
||||||
|
|
||||||
twod->ClearTransform();
|
twod->ClearTransform();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -87,6 +87,7 @@ void FGLRenderBuffers::ClearScene()
|
||||||
|
|
||||||
void FGLRenderBuffers::ClearPipeline()
|
void FGLRenderBuffers::ClearPipeline()
|
||||||
{
|
{
|
||||||
|
DeleteRenderBuffer(mPipelineDepthStencilBuf);
|
||||||
for (int i = 0; i < NumPipelineTextures; i++)
|
for (int i = 0; i < NumPipelineTextures; i++)
|
||||||
{
|
{
|
||||||
DeleteFrameBuffer(mPipelineFB[i]);
|
DeleteFrameBuffer(mPipelineFB[i]);
|
||||||
|
@ -239,10 +240,11 @@ void FGLRenderBuffers::CreatePipeline(int width, int height)
|
||||||
ClearPipeline();
|
ClearPipeline();
|
||||||
ClearEyeBuffers();
|
ClearEyeBuffers();
|
||||||
|
|
||||||
|
mPipelineDepthStencilBuf = CreateRenderBuffer("PipelineDepthStencil", GL_DEPTH24_STENCIL8, width, height);
|
||||||
for (int i = 0; i < NumPipelineTextures; i++)
|
for (int i = 0; i < NumPipelineTextures; i++)
|
||||||
{
|
{
|
||||||
mPipelineTexture[i] = Create2DTexture("PipelineTexture", GL_RGBA16F, width, height);
|
mPipelineTexture[i] = Create2DTexture("PipelineTexture", GL_RGBA16F, width, height);
|
||||||
mPipelineFB[i] = CreateFrameBuffer("PipelineFB", mPipelineTexture[i]);
|
mPipelineFB[i] = CreateFrameBuffer("PipelineFB", mPipelineTexture[i], mPipelineDepthStencilBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,7 @@ private:
|
||||||
|
|
||||||
static const int NumPipelineTextures = 2;
|
static const int NumPipelineTextures = 2;
|
||||||
int mCurrentPipelineTexture = 0;
|
int mCurrentPipelineTexture = 0;
|
||||||
|
PPGLRenderBuffer mPipelineDepthStencilBuf;
|
||||||
|
|
||||||
// Buffers for the scene
|
// Buffers for the scene
|
||||||
PPGLTexture mSceneMultisampleTex;
|
PPGLTexture mSceneMultisampleTex;
|
||||||
|
|
|
@ -59,6 +59,9 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
|
||||||
state.SetViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
state.SetViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height);
|
||||||
screen->mViewpoints->Set2D(state, twod->GetWidth(), twod->GetHeight());
|
screen->mViewpoints->Set2D(state, twod->GetWidth(), twod->GetHeight());
|
||||||
|
|
||||||
|
state.EnableStencil(false);
|
||||||
|
state.SetStencil(0, SOP_Keep, SF_AllOn);
|
||||||
|
state.Clear(CT_Stencil);
|
||||||
state.EnableDepthTest(false);
|
state.EnableDepthTest(false);
|
||||||
state.EnableMultisampling(false);
|
state.EnableMultisampling(false);
|
||||||
state.EnableLineSmooth(gl_aalines);
|
state.EnableLineSmooth(gl_aalines);
|
||||||
|
@ -88,6 +91,22 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
|
||||||
|
|
||||||
for(auto &cmd : commands)
|
for(auto &cmd : commands)
|
||||||
{
|
{
|
||||||
|
if (cmd.isSpecial != SpecialDrawCommand::NotSpecial)
|
||||||
|
{
|
||||||
|
if (cmd.isSpecial == SpecialDrawCommand::EnableStencil)
|
||||||
|
{
|
||||||
|
state.EnableStencil(cmd.stencilOn);
|
||||||
|
}
|
||||||
|
else if (cmd.isSpecial == SpecialDrawCommand::SetStencil)
|
||||||
|
{
|
||||||
|
state.SetStencil(cmd.stencilOffs, cmd.stencilOp, cmd.stencilFlags);
|
||||||
|
}
|
||||||
|
else if (cmd.isSpecial == SpecialDrawCommand::ClearStencil)
|
||||||
|
{
|
||||||
|
state.Clear(CT_Stencil);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
state.SetRenderStyle(cmd.mRenderStyle);
|
state.SetRenderStyle(cmd.mRenderStyle);
|
||||||
state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
|
state.EnableBrightmap(!(cmd.mRenderStyle.Flags & STYLEF_ColorIsFixed));
|
||||||
|
@ -126,7 +145,7 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
|
||||||
if (cmd.mFlags & F2DDrawer::DTF_Indexed) state.SetSoftLightLevel(cmd.mLightLevel);
|
if (cmd.mFlags & F2DDrawer::DTF_Indexed) state.SetSoftLightLevel(cmd.mLightLevel);
|
||||||
state.SetLightParms(0, 0);
|
state.SetLightParms(0, 0);
|
||||||
|
|
||||||
state.AlphaFunc(Alpha_GEqual, 0.f);
|
state.AlphaFunc(Alpha_Greater, 0.f);
|
||||||
|
|
||||||
if (cmd.useTransform)
|
if (cmd.useTransform)
|
||||||
{
|
{
|
||||||
|
@ -225,6 +244,8 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state)
|
||||||
|
|
||||||
state.SetRenderStyle(STYLE_Translucent);
|
state.SetRenderStyle(STYLE_Translucent);
|
||||||
state.SetVertexBuffer(screen->mVertexData);
|
state.SetVertexBuffer(screen->mVertexData);
|
||||||
|
state.EnableStencil(false);
|
||||||
|
state.SetStencil(0, SOP_Keep, SF_AllOn);
|
||||||
state.EnableTexture(true);
|
state.EnableTexture(true);
|
||||||
state.EnableBrightmap(true);
|
state.EnableBrightmap(true);
|
||||||
state.SetTextureMode(TM_NORMAL);
|
state.SetTextureMode(TM_NORMAL);
|
||||||
|
|
|
@ -57,9 +57,10 @@ void VkPostprocess::SetActiveRenderTarget()
|
||||||
|
|
||||||
VkImageTransition()
|
VkImageTransition()
|
||||||
.AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false)
|
.AddImage(&buffers->PipelineImage[mCurrentPipelineImage], VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, false)
|
||||||
|
.AddImage(&buffers->PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false)
|
||||||
.Execute(fb->GetCommands()->GetDrawCommands());
|
.Execute(fb->GetCommands()->GetDrawCommands());
|
||||||
|
|
||||||
fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], nullptr, buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
|
fb->GetRenderState()->SetRenderTarget(&buffers->PipelineImage[mCurrentPipelineImage], buffers->PipelineDepthStencil.View.get(), buffers->GetWidth(), buffers->GetHeight(), VK_FORMAT_R16G16B16A16_SFLOAT, VK_SAMPLE_COUNT_1_BIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D)
|
void VkPostprocess::PostProcessScene(int fixedcm, float flash, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||||
|
|
|
@ -71,12 +71,12 @@ void VkPPRenderState::Draw()
|
||||||
|
|
||||||
if (Output.Type == PPTextureType::SceneColor)
|
if (Output.Type == PPTextureType::SceneColor)
|
||||||
{
|
{
|
||||||
key.StencilTest = 1;
|
key.StencilTest = WhichDepthStencil::Scene;
|
||||||
key.Samples = fb->GetBuffers()->GetSceneSamples();
|
key.Samples = fb->GetBuffers()->GetSceneSamples();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
key.StencilTest = 0;
|
key.StencilTest = WhichDepthStencil::None;
|
||||||
key.Samples = VK_SAMPLE_COUNT_1_BIT;
|
key.Samples = VK_SAMPLE_COUNT_1_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ void VkPPRenderState::Draw()
|
||||||
VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers);
|
VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers);
|
||||||
VulkanFramebuffer *output = fb->GetBuffers()->GetOutput(passSetup, Output, key.StencilTest, framebufferWidth, framebufferHeight);
|
VulkanFramebuffer *output = fb->GetBuffers()->GetOutput(passSetup, Output, key.StencilTest, framebufferWidth, framebufferHeight);
|
||||||
|
|
||||||
RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest);
|
RenderScreenQuad(passSetup, input, output, framebufferWidth, framebufferHeight, Viewport.left, Viewport.top, Viewport.width, Viewport.height, Uniforms.Data.Data(), Uniforms.Data.Size(), key.StencilTest == WhichDepthStencil::Scene);
|
||||||
|
|
||||||
// Advance to next PP texture if our output was sent there
|
// Advance to next PP texture if our output was sent there
|
||||||
if (Output.Type == PPTextureType::NextPipelineTexture)
|
if (Output.Type == PPTextureType::NextPipelineTexture)
|
||||||
|
|
|
@ -342,7 +342,7 @@ void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey& key)
|
||||||
// Note: the actual values are ignored since we use dynamic viewport+scissor states
|
// Note: the actual values are ignored since we use dynamic viewport+scissor states
|
||||||
builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f);
|
builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f);
|
||||||
builder.Scissor(0, 0, 320, 200);
|
builder.Scissor(0, 0, 320, 200);
|
||||||
if (key.StencilTest)
|
if (key.StencilTest != WhichDepthStencil::None)
|
||||||
{
|
{
|
||||||
builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE);
|
||||||
builder.DepthStencilEnable(false, false, true);
|
builder.DepthStencilEnable(false, false, true);
|
||||||
|
@ -364,7 +364,7 @@ void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey& key)
|
||||||
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_CLEAR, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||||
else
|
else
|
||||||
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
builder.AddAttachment(key.OutputFormat, key.Samples, VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
if (key.StencilTest)
|
if (key.StencilTest == WhichDepthStencil::Scene)
|
||||||
{
|
{
|
||||||
builder.AddDepthStencilAttachment(
|
builder.AddDepthStencilAttachment(
|
||||||
fb->GetBuffers()->SceneDepthStencilFormat, key.Samples,
|
fb->GetBuffers()->SceneDepthStencilFormat, key.Samples,
|
||||||
|
@ -372,10 +372,18 @@ void VkPPRenderPassSetup::CreateRenderPass(const VkPPRenderPassKey& key)
|
||||||
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
}
|
}
|
||||||
|
if (key.StencilTest == WhichDepthStencil::Pipeline)
|
||||||
|
{
|
||||||
|
builder.AddDepthStencilAttachment(
|
||||||
|
fb->GetBuffers()->PipelineDepthStencilFormat, key.Samples,
|
||||||
|
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE,
|
||||||
|
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
|
}
|
||||||
|
|
||||||
builder.AddSubpass();
|
builder.AddSubpass();
|
||||||
builder.AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
builder.AddSubpassColorAttachmentRef(0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);
|
||||||
if (key.StencilTest)
|
if (key.StencilTest != WhichDepthStencil::None)
|
||||||
{
|
{
|
||||||
builder.AddSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
builder.AddSubpassDepthStencilAttachmentRef(1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL);
|
||||||
builder.AddExternalSubpassDependency(
|
builder.AddExternalSubpassDependency(
|
||||||
|
|
|
@ -78,6 +78,8 @@ public:
|
||||||
int UseVertexData;
|
int UseVertexData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class WhichDepthStencil;
|
||||||
|
|
||||||
class VkPPRenderPassKey
|
class VkPPRenderPassKey
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -88,7 +90,7 @@ public:
|
||||||
VkFormat OutputFormat;
|
VkFormat OutputFormat;
|
||||||
int SwapChain;
|
int SwapChain;
|
||||||
int ShadowMapBuffers;
|
int ShadowMapBuffers;
|
||||||
int StencilTest;
|
WhichDepthStencil StencilTest;
|
||||||
VkSampleCountFlagBits Samples;
|
VkSampleCountFlagBits Samples;
|
||||||
|
|
||||||
bool operator<(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
|
bool operator<(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; }
|
||||||
|
|
|
@ -83,14 +83,49 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen
|
||||||
mSceneHeight = sceneHeight;
|
mSceneHeight = sceneHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VkRenderBuffers::CreatePipelineDepthStencil(int width, int height)
|
||||||
|
{
|
||||||
|
ImageBuilder builder;
|
||||||
|
builder.Size(width, height);
|
||||||
|
builder.Format(PipelineDepthStencilFormat);
|
||||||
|
builder.Usage(VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||||
|
if (!builder.IsFormatSupported(fb->device))
|
||||||
|
{
|
||||||
|
PipelineDepthStencilFormat = VK_FORMAT_D32_SFLOAT_S8_UINT;
|
||||||
|
builder.Format(PipelineDepthStencilFormat);
|
||||||
|
if (!builder.IsFormatSupported(fb->device))
|
||||||
|
{
|
||||||
|
I_FatalError("This device does not support any of the required depth stencil image formats.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.DebugName("VkRenderBuffers.PipelineDepthStencil");
|
||||||
|
|
||||||
|
PipelineDepthStencil.Image = builder.Create(fb->device);
|
||||||
|
PipelineDepthStencil.AspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
|
||||||
|
|
||||||
|
PipelineDepthStencil.View = ImageViewBuilder()
|
||||||
|
.Image(PipelineDepthStencil.Image.get(), PipelineDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)
|
||||||
|
.DebugName("VkRenderBuffers.PipelineDepthStencilView")
|
||||||
|
.Create(fb->device);
|
||||||
|
|
||||||
|
PipelineDepthStencil.DepthOnlyView = ImageViewBuilder()
|
||||||
|
.Image(PipelineDepthStencil.Image.get(), PipelineDepthStencilFormat, VK_IMAGE_ASPECT_DEPTH_BIT)
|
||||||
|
.DebugName("VkRenderBuffers.PipelineDepthView")
|
||||||
|
.Create(fb->device);
|
||||||
|
}
|
||||||
|
|
||||||
void VkRenderBuffers::CreatePipeline(int width, int height)
|
void VkRenderBuffers::CreatePipeline(int width, int height)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < NumPipelineImages; i++)
|
for (int i = 0; i < NumPipelineImages; i++)
|
||||||
{
|
{
|
||||||
PipelineImage[i].Reset(fb);
|
PipelineImage[i].Reset(fb);
|
||||||
}
|
}
|
||||||
|
PipelineDepthStencil.Reset(fb);
|
||||||
|
|
||||||
|
CreatePipelineDepthStencil(width, height);
|
||||||
|
|
||||||
VkImageTransition barrier;
|
VkImageTransition barrier;
|
||||||
|
barrier.AddImage(&PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true);
|
||||||
for (int i = 0; i < NumPipelineImages; i++)
|
for (int i = 0; i < NumPipelineImages; i++)
|
||||||
{
|
{
|
||||||
PipelineImage[i].Image = ImageBuilder()
|
PipelineImage[i].Image = ImageBuilder()
|
||||||
|
@ -216,7 +251,7 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag
|
||||||
.Create(fb->device);
|
.Create(fb->device);
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, bool stencilTest, int& framebufferWidth, int& framebufferHeight)
|
VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, WhichDepthStencil stencilTest, int& framebufferWidth, int& framebufferHeight)
|
||||||
{
|
{
|
||||||
VkTextureImage* tex = fb->GetTextureManager()->GetTexture(output.Type, output.Texture);
|
VkTextureImage* tex = fb->GetTextureManager()->GetTexture(output.Type, output.Texture);
|
||||||
|
|
||||||
|
@ -227,8 +262,12 @@ VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, co
|
||||||
{
|
{
|
||||||
VkImageTransition imageTransition;
|
VkImageTransition imageTransition;
|
||||||
imageTransition.AddImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture);
|
imageTransition.AddImage(tex, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, output.Type == PPTextureType::NextPipelineTexture);
|
||||||
if (stencilTest)
|
if (stencilTest == WhichDepthStencil::Scene)
|
||||||
imageTransition.AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false);
|
imageTransition.AddImage(&fb->GetBuffers()->SceneDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false);
|
||||||
|
|
||||||
|
if (stencilTest == WhichDepthStencil::Pipeline)
|
||||||
|
imageTransition.AddImage(&fb->GetBuffers()->PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false);
|
||||||
|
|
||||||
imageTransition.Execute(fb->GetCommands()->GetDrawCommands());
|
imageTransition.Execute(fb->GetCommands()->GetDrawCommands());
|
||||||
|
|
||||||
view = tex->View->view;
|
view = tex->View->view;
|
||||||
|
@ -251,8 +290,10 @@ VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, co
|
||||||
builder.RenderPass(passSetup->RenderPass.get());
|
builder.RenderPass(passSetup->RenderPass.get());
|
||||||
builder.Size(w, h);
|
builder.Size(w, h);
|
||||||
builder.AddAttachment(view);
|
builder.AddAttachment(view);
|
||||||
if (stencilTest)
|
if (stencilTest == WhichDepthStencil::Scene)
|
||||||
builder.AddAttachment(fb->GetBuffers()->SceneDepthStencil.View.get());
|
builder.AddAttachment(fb->GetBuffers()->SceneDepthStencil.View.get());
|
||||||
|
if (stencilTest == WhichDepthStencil::Pipeline)
|
||||||
|
builder.AddAttachment(fb->GetBuffers()->PipelineDepthStencil.View.get());
|
||||||
builder.DebugName("PPOutputFB");
|
builder.DebugName("PPOutputFB");
|
||||||
framebuffer = builder.Create(fb->device);
|
framebuffer = builder.Create(fb->device);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,12 @@ class VulkanFrameBuffer;
|
||||||
class VkPPRenderPassSetup;
|
class VkPPRenderPassSetup;
|
||||||
class PPOutput;
|
class PPOutput;
|
||||||
|
|
||||||
|
enum class WhichDepthStencil {
|
||||||
|
None,
|
||||||
|
Scene,
|
||||||
|
Pipeline,
|
||||||
|
};
|
||||||
|
|
||||||
class VkRenderBuffers
|
class VkRenderBuffers
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -27,15 +33,18 @@ public:
|
||||||
VkTextureImage SceneNormal;
|
VkTextureImage SceneNormal;
|
||||||
VkTextureImage SceneFog;
|
VkTextureImage SceneFog;
|
||||||
|
|
||||||
|
VkFormat PipelineDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||||
VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
|
VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT;
|
||||||
VkFormat SceneNormalFormat = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
|
VkFormat SceneNormalFormat = VK_FORMAT_A2R10G10B10_UNORM_PACK32;
|
||||||
|
|
||||||
static const int NumPipelineImages = 2;
|
static const int NumPipelineImages = 2;
|
||||||
|
VkTextureImage PipelineDepthStencil;
|
||||||
VkTextureImage PipelineImage[NumPipelineImages];
|
VkTextureImage PipelineImage[NumPipelineImages];
|
||||||
|
|
||||||
VulkanFramebuffer* GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, bool stencilTest, int& framebufferWidth, int& framebufferHeight);
|
VulkanFramebuffer* GetOutput(VkPPRenderPassSetup* passSetup, const PPOutput& output, WhichDepthStencil stencilTest, int& framebufferWidth, int& framebufferHeight);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void CreatePipelineDepthStencil(int width, int height);
|
||||||
void CreatePipeline(int width, int height);
|
void CreatePipeline(int width, int height);
|
||||||
void CreateScene(int width, int height, VkSampleCountFlagBits samples);
|
void CreateScene(int width, int height, VkSampleCountFlagBits samples);
|
||||||
void CreateSceneColor(int width, int height, VkSampleCountFlagBits samples);
|
void CreateSceneColor(int width, int height, VkSampleCountFlagBits samples);
|
||||||
|
|
|
@ -463,6 +463,19 @@ enum DrawTextureTags
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum StencilOp
|
||||||
|
{
|
||||||
|
SOP_Keep = 0,
|
||||||
|
SOP_Increment = 1,
|
||||||
|
SOP_Decrement = 2
|
||||||
|
};
|
||||||
|
enum StencilFlags
|
||||||
|
{
|
||||||
|
SF_AllOn = 0,
|
||||||
|
SF_ColorMaskOff = 1,
|
||||||
|
SF_DepthMaskOff = 2
|
||||||
|
};
|
||||||
|
|
||||||
class Shape2DTransform : Object native
|
class Shape2DTransform : Object native
|
||||||
{
|
{
|
||||||
native void Clear();
|
native void Clear();
|
||||||
|
@ -516,6 +529,9 @@ struct Screen native
|
||||||
native static void ClearScreen(color col = 0);
|
native static void ClearScreen(color col = 0);
|
||||||
native static void SetScreenFade(double factor);
|
native static void SetScreenFade(double factor);
|
||||||
|
|
||||||
|
native static void EnableStencil(bool on);
|
||||||
|
native static void SetStencil(int offs, int op, int flags = -1);
|
||||||
|
native static void ClearStencil();
|
||||||
native static void SetTransform(Shape2DTransform transform);
|
native static void SetTransform(Shape2DTransform transform);
|
||||||
native static void ClearTransform();
|
native static void ClearTransform();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue