From 6591b3b0902911f6c5adcf720a3471a5bfcd4ad4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sat, 23 Jul 2022 12:05:27 +0200 Subject: [PATCH] - Backend update from GZDoom. Mainly new features for 2D drawer and model renderer. --- source/common/2d/v_2ddrawer.cpp | 190 ++++++++++++++---- source/common/2d/v_2ddrawer.h | 37 +++- source/common/2d/v_draw.cpp | 91 ++++++++- source/common/models/model.cpp | 1 + source/common/models/model.h | 9 +- source/common/models/model_kvx.h | 4 +- source/common/models/model_md2.h | 8 +- source/common/models/model_md3.h | 8 +- source/common/models/model_obj.h | 4 +- source/common/models/model_ue1.h | 4 +- source/common/models/models_md2.cpp | 4 +- source/common/models/models_md3.cpp | 25 +-- source/common/models/models_obj.cpp | 16 +- source/common/models/models_ue1.cpp | 14 +- source/common/models/models_voxel.cpp | 4 +- .../common/rendering/gl/gl_renderbuffers.cpp | 6 +- source/common/rendering/gl/gl_renderbuffers.h | 3 +- .../common/rendering/hwrenderer/hw_draw2d.cpp | 23 ++- .../vulkan/renderer/vk_postprocess.cpp | 3 +- .../vulkan/renderer/vk_pprenderstate.cpp | 6 +- .../rendering/vulkan/renderer/vk_raytrace.cpp | 74 ++++--- .../vulkan/renderer/vk_renderpass.cpp | 18 +- .../rendering/vulkan/renderer/vk_renderpass.h | 4 +- .../rendering/vulkan/system/vk_builders.cpp | 40 ++++ .../rendering/vulkan/system/vk_builders.h | 17 ++ .../vulkan/textures/vk_renderbuffers.cpp | 47 ++++- .../vulkan/textures/vk_renderbuffers.h | 11 +- source/core/rendering/scene/hw_sprites.cpp | 2 +- source/glbackend/glbackend.cpp | 2 +- wadsrc/static/zscript/engine/base.zs | 21 ++ wadsrc/static/zscript/engine/screenjob.zs | 8 + 31 files changed, 550 insertions(+), 154 deletions(-) diff --git a/source/common/2d/v_2ddrawer.cpp b/source/common/2d/v_2ddrawer.cpp index 69ab0d530..5231ceec0 100644 --- a/source/common/2d/v_2ddrawer.cpp +++ b/source/common/2d/v_2ddrawer.cpp @@ -104,6 +104,33 @@ DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, Translate, Shape2DTransform_Tra return 0; } +static void Shape2DTransform_From2D( + DShape2DTransform* self, + double m00, double m01, double m10, double m11, double vx, double vy +) +{ + self->transform.Cells[0][0] = m00; + self->transform.Cells[0][1] = m01; + self->transform.Cells[1][0] = m10; + self->transform.Cells[1][1] = m11; + + self->transform.Cells[0][2] = vx; + self->transform.Cells[1][2] = vy; +} + +DEFINE_ACTION_FUNCTION_NATIVE(DShape2DTransform, From2D, Shape2DTransform_From2D) +{ + PARAM_SELF_PROLOGUE(DShape2DTransform); + PARAM_FLOAT(m00); + PARAM_FLOAT(m01); + PARAM_FLOAT(m10); + PARAM_FLOAT(m11); + PARAM_FLOAT(vx); + PARAM_FLOAT(vy); + Shape2DTransform_From2D(self, m00, m01, m10, m11, vx, vy); + return 0; +} + IMPLEMENT_CLASS(DShape2D, false, false) static void Shape2D_SetTransform(DShape2D* self, DShape2DTransform *transform) @@ -114,7 +141,7 @@ static void Shape2D_SetTransform(DShape2D* self, DShape2DTransform *transform) DEFINE_ACTION_FUNCTION_NATIVE(DShape2D, SetTransform, Shape2D_SetTransform) { PARAM_SELF_PROLOGUE(DShape2D); - PARAM_OBJECT(transform, DShape2DTransform); + PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform); Shape2D_SetTransform(self, transform); return 0; } @@ -462,8 +489,19 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) u1 = float(u1 + parms.windowleft / parms.texwidth); u2 = float(u2 - (parms.texwidth - wi) / parms.texwidth); } + auto t = this->transform; + auto tCorners = { + (t * DVector3(x, y, 1.0)).XY(), + (t * DVector3(x, y + h, 1.0)).XY(), + (t * DVector3(x + w, y, 1.0)).XY(), + (t * DVector3(x + w, y + h, 1.0)).XY() + }; + double minx = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; + double maxx = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; + double miny = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.Y < d1.Y; })->Y; + double maxy = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.Y < d1.Y; })->Y; - if (x < (double)parms.lclip || y < (double)parms.uclip || x + w >(double)parms.rclip || y + h >(double)parms.dclip) + if (minx < (double)parms.lclip || miny < (double)parms.uclip || maxx >(double)parms.rclip || maxy >(double)parms.dclip) { dg.mScissor[0] = parms.lclip + int(offset.X); dg.mScissor[1] = parms.uclip + int(offset.Y); @@ -479,10 +517,10 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) dg.mVertCount = 4; dg.mVertIndex = (int)mVertices.Reserve(4); TwoDVertex* ptr = &mVertices[dg.mVertIndex]; - Set(ptr, x, y, 0, u1, v1, vertexcolor); ptr++; - Set(ptr, x, y + h, 0, u1, v2, vertexcolor); ptr++; - Set(ptr, x + w, y, 0, u2, v1, vertexcolor); ptr++; - Set(ptr, x + w, y + h, 0, u2, v2, vertexcolor); ptr++; + ptr->Set(x, y, 0, u1, v1, vertexcolor); ptr++; + ptr->Set(x, y + h, 0, u1, v2, vertexcolor); ptr++; + ptr->Set(x + w, y, 0, u2, v1, vertexcolor); ptr++; + ptr->Set(x + w, y + h, 0, u2, v2, vertexcolor); ptr++; } else { @@ -515,12 +553,16 @@ void F2DDrawer::AddTexture(FGameTexture* img, DrawParms& parms) dg.mVertCount = 4; dg.mVertIndex = (int)mVertices.Reserve(4); TwoDVertex* ptr = &mVertices[dg.mVertIndex]; - Set(ptr, x1, y1, 0, u1, v1, vertexcolor); ptr++; - Set(ptr, x2, y2, 0, u1, v2, vertexcolor); ptr++; - Set(ptr, x3, y3, 0, u2, v1, vertexcolor); ptr++; - Set(ptr, x4, y4, 0, u2, v2, vertexcolor); ptr++; + ptr->Set(x1, y1, 0, u1, v1, vertexcolor); ptr++; + ptr->Set(x2, y2, 0, u1, v2, vertexcolor); ptr++; + ptr->Set(x3, y3, 0, u2, v1, vertexcolor); ptr++; + ptr->Set(x4, y4, 0, u2, v2, vertexcolor); ptr++; } + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -579,7 +621,7 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) shape->lastParms = new DrawParms(parms); } - if (!img->isHardwareCanvas() && parms.TranslationId != -1) + if (!(img != nullptr && img->isHardwareCanvas()) && parms.TranslationId != -1) dg.mTranslationId = parms.TranslationId; auto osave = offset; @@ -599,11 +641,12 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) if ( shape->mVertices[i].Y > shape->maxy ) shape->maxy = shape->mVertices[i].Y; } } + auto t = this->transform * shape->transform; auto tCorners = { - (shape->transform * DVector3(shape->minx, shape->miny, 1.0)).XY(), - (shape->transform * DVector3(shape->minx, shape->maxy, 1.0)).XY(), - (shape->transform * DVector3(shape->maxx, shape->miny, 1.0)).XY(), - (shape->transform * DVector3(shape->maxx, shape->maxy, 1.0)).XY() + (t * DVector3(shape->minx, shape->miny, 1.0)).XY(), + (t * DVector3(shape->minx, shape->maxy, 1.0)).XY(), + (t * DVector3(shape->maxx, shape->miny, 1.0)).XY(), + (t * DVector3(shape->maxx, shape->maxy, 1.0)).XY() }; double minx = std::min_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; double maxx = std::max_element(tCorners.begin(), tCorners.end(), [] (auto d0, auto d1) { return d0.X < d1.X; })->X; @@ -621,7 +664,7 @@ void F2DDrawer::AddShape(FGameTexture* img, DShape2D* shape, DrawParms& parms) memset(dg.mScissor, 0, sizeof(dg.mScissor)); dg.useTransform = true; - dg.transform = shape->transform; + dg.transform = t; dg.transform.Cells[0][2] += offset.X; dg.transform.Cells[1][2] += offset.Y; dg.shape2DBufInfo = shape->bufferInfo; @@ -715,7 +758,7 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints, u = t * cosrot - v * sinrot; v = v * cosrot + t * sinrot; } - Set(&mVertices[poly.mVertIndex+i], points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0); + mVertices[poly.mVertIndex+i].Set(points[i].X, points[i].Y, 0, u*uscale, v*vscale, color0); } poly.mIndexIndex = mIndices.Size(); @@ -736,6 +779,10 @@ void F2DDrawer::AddPoly(FGameTexture *texture, FVector2 *points, int npoints, mIndices[addr + i] = poly.mVertIndex + indices[i]; } } + poly.useTransform = true; + poly.transform = this->transform; + poly.transform.Cells[0][2] += offset.X; + poly.transform.Cells[1][2] += offset.Y; AddCommand(&poly); } @@ -773,7 +820,7 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const u for (size_t i=0;iSet(vt[i].X, vt[i].Y, 0.f, vt[i].Z, vt[i].W, color); ptr++; } dg.mIndexIndex = mIndices.Size(); @@ -798,6 +845,10 @@ void F2DDrawer::AddPoly(FGameTexture* img, FVector4* vt, size_t vtcount, const u dg.mIndexCount = (int)vtcount; } + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; AddCommand(&dg); } @@ -916,18 +967,22 @@ void F2DDrawer::AddFlatFill(int left, int top, int right, int bottom, FGameTextu dg.mVertIndex = (int)mVertices.Reserve(4); auto ptr = &mVertices[dg.mVertIndex]; - Set(ptr, left, top, 0, fU1, fV1, color); ptr++; + ptr->Set(left, top, 0, fU1, fV1, color); ptr++; if (local_origin < 4) { - Set(ptr, left, bottom, 0, fU1, fV2, color); ptr++; - Set(ptr, right, top, 0, fU2, fV1, color); ptr++; + ptr->Set(left, bottom, 0, fU1, fV2, color); ptr++; + ptr->Set(right, top, 0, fU2, fV1, color); ptr++; } else { - Set(ptr, left, bottom, 0, fU2, fV1, color); ptr++; - Set(ptr, right, top, 0, fU1, fV2, color); ptr++; + ptr->Set(left, bottom, 0, fU2, fV1, color); ptr++; + ptr->Set(right, top, 0, fU1, fV2, color); ptr++; } - Set(ptr, right, bottom, 0, fU2, fV2, color); ptr++; + ptr->Set(right, bottom, 0, fU2, fV2, color); ptr++; + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -950,10 +1005,14 @@ void F2DDrawer::AddColorOnlyQuad(int x1, int y1, int w, int h, PalEntry color, F dg.mVertIndex = (int)mVertices.Reserve(4); dg.mRenderStyle = style? *style : LegacyRenderStyles[STYLE_Translucent]; auto ptr = &mVertices[dg.mVertIndex]; - Set(ptr, x1, y1, 0, 0, 0, color); ptr++; - Set(ptr, x1, y1 + h, 0, 0, 0, color); ptr++; - Set(ptr, x1 + w, y1, 0, 0, 0, color); ptr++; - Set(ptr, x1 + w, y1 + h, 0, 0, 0, color); ptr++; + ptr->Set(x1, y1, 0, 0, 0, color); ptr++; + ptr->Set(x1, y1 + h, 0, 0, 0, color); ptr++; + ptr->Set(x1 + w, y1, 0, 0, 0, color); ptr++; + ptr->Set(x1 + w, y1 + h, 0, 0, 0, color); ptr++; + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -998,8 +1057,12 @@ void F2DDrawer::AddLine(double x1, double y1, double x2, double y2, int clipx1, dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; dg.mVertCount = 2; dg.mVertIndex = (int)mVertices.Reserve(2); - Set(&mVertices[dg.mVertIndex], x1, y1, 0, 0, 0, p); - Set(&mVertices[dg.mVertIndex+1], x2, y2, 0, 0, 0, p); + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; + mVertices[dg.mVertIndex].Set(x1, y1, 0, 0, 0, p); + mVertices[dg.mVertIndex+1].Set(x2, y2, 0, 0, 0, p); AddCommand(&dg); } @@ -1034,10 +1097,14 @@ void F2DDrawer::AddThickLine(int x1, int y1, int x2, int y2, double thickness, u dg.mVertIndex = (int)mVertices.Reserve(4); dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; auto ptr = &mVertices[dg.mVertIndex]; - Set(ptr, corner0.X, corner0.Y, 0, 0, 0, p); ptr++; - Set(ptr, corner1.X, corner1.Y, 0, 0, 0, p); ptr++; - Set(ptr, corner2.X, corner2.Y, 0, 0, 0, p); ptr++; - Set(ptr, corner3.X, corner3.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner0.X, corner0.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner1.X, corner1.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner2.X, corner2.Y, 0, 0, 0, p); ptr++; + ptr->Set(corner3.X, corner3.Y, 0, 0, 0, p); ptr++; + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; dg.mIndexIndex = mIndices.Size(); dg.mIndexCount += 6; AddIndices(dg.mVertIndex, 6, 0, 1, 2, 1, 3, 2); @@ -1061,7 +1128,60 @@ void F2DDrawer::AddPixel(int x1, int y1, uint32_t color) dg.mRenderStyle = LegacyRenderStyles[STYLE_Translucent]; dg.mVertCount = 1; dg.mVertIndex = (int)mVertices.Reserve(1); - Set(&mVertices[dg.mVertIndex], x1, y1, 0, 0, 0, p); + mVertices[dg.mVertIndex].Set(x1, y1, 0, 0, 0, p); + dg.useTransform = true; + dg.transform = this->transform; + dg.transform.Cells[0][2] += offset.X; + dg.transform.Cells[1][2] += offset.Y; + AddCommand(&dg); +} + +//========================================================================== +// +// +// +//========================================================================== + +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); } diff --git a/source/common/2d/v_2ddrawer.h b/source/common/2d/v_2ddrawer.h index 623559978..d718e06d4 100644 --- a/source/common/2d/v_2ddrawer.h +++ b/source/common/2d/v_2ddrawer.h @@ -52,9 +52,20 @@ struct F2DPolygons class DShape2D; struct DShape2DBufferInfo; +enum class SpecialDrawCommand { + NotSpecial, + + EnableStencil, + SetStencil, + ClearStencil, +}; + class F2DDrawer { public: + F2DDrawer() { + this->transform.Identity(); + } enum EDrawType : uint8_t { @@ -104,6 +115,14 @@ public: struct RenderCommand { + SpecialDrawCommand isSpecial; + + bool stencilOn; + + int stencilOffs; + int stencilOp; + int stencilFlags; + EDrawType mType; int mVertIndex; int mVertCount; @@ -138,6 +157,10 @@ public: // If these fields match, two draw commands can be batched. bool isCompatible(const RenderCommand &other) const { + if ( + isSpecial != SpecialDrawCommand::NotSpecial || + other.isSpecial != SpecialDrawCommand::NotSpecial + ) return false; if (shape2DBufInfo != nullptr || other.shape2DBufInfo != nullptr) return false; return mTexture == other.mTexture && mType == other.mType && @@ -172,6 +195,7 @@ public: bool locked; // prevents clearing of the data so it can be reused multiple times (useful for screen fades) float screenFade = 1.f; DVector2 offset; + DMatrix3x3 transform; public: int fullscreenautoaspect = 3; int cliptop = -1, clipleft = -1, clipwidth = -1, clipheight = -1; @@ -206,6 +230,10 @@ public: 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 AddEnableStencil(bool on); + void AddSetStencil(int offs, int op, int flags); + void AddClearStencil(); + void Clear(); void Lock() { locked = true; } void SetScreenFade(float factor) { screenFade = factor; } @@ -229,11 +257,14 @@ public: return v; } - void Set(TwoDVertex* v, double xx, double yy, double zz, double uu, double vv, PalEntry col) + void SetTransform(const DShape2DTransform& transform) { - v->Set(xx + offset.X, yy + offset.Y, zz, uu, vv, col); + this->transform = transform.transform; + } + void ClearTransform() + { + this->transform.Identity(); } - int DrawCount() const { diff --git a/source/common/2d/v_draw.cpp b/source/common/2d/v_draw.cpp index e41a2eec8..54c9cc904 100644 --- a/source/common/2d/v_draw.cpp +++ b/source/common/2d/v_draw.cpp @@ -289,6 +289,19 @@ void DrawShape(F2DDrawer *drawer, FGameTexture *img, DShape2D *shape, VMVa_List drawer->AddShape(img, shape, parms); } +void DrawShapeFill(F2DDrawer *drawer, int color, DShape2D *shape, VMVa_List &args) +{ + DrawParms parms; + uint32_t tag = ListGetInt(args); + + bool res = ParseDrawTextureTags(drawer, nullptr, 0, 0, tag, args, &parms, false, false); + if (!res) return; + + parms.fillcolor = color; + + drawer->AddShape(nullptr, shape, parms); +} + DEFINE_ACTION_FUNCTION(_Screen, DrawShape) { PARAM_PROLOGUE; @@ -307,6 +320,25 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawShape) return 0; } +DEFINE_ACTION_FUNCTION(_Screen, DrawShapeFill) +{ + PARAM_PROLOGUE; + PARAM_COLOR(color); + PARAM_FLOAT(amount); + PARAM_POINTER(shape, DShape2D); + + PARAM_VA_POINTER(va_reginfo) // Get the hidden type information array + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + VMVa_List args = { param + 3, 0, numparam - 4, va_reginfo + 3 }; + + color.a = int(amount * 255.0f); + + DrawShapeFill(twod, color, shape, args); + return 0; +} + //========================================================================== // // Clipping rect @@ -1624,4 +1656,61 @@ DEFINE_ACTION_FUNCTION(_Screen, SetOffset) PARAM_FLOAT(x); PARAM_FLOAT(y); ACTION_RETURN_VEC2(twod->SetOffset(DVector2(x, y))); -} \ No newline at end of file +} + +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) +{ + PARAM_PROLOGUE; + PARAM_OBJECT_NOT_NULL(transform, DShape2DTransform); + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + twod->SetTransform(*transform); + + return 0; +} + +DEFINE_ACTION_FUNCTION(_Screen, ClearTransform) +{ + PARAM_PROLOGUE; + + if (!twod->HasBegun2D()) ThrowAbortException(X_OTHER, "Attempt to draw to screen outside a draw function"); + + twod->ClearTransform(); + return 0; +} + diff --git a/source/common/models/model.cpp b/source/common/models/model.cpp index e8826d5b8..1829ccebb 100644 --- a/source/common/models/model.cpp +++ b/source/common/models/model.cpp @@ -42,6 +42,7 @@ #include "modelrenderer.h" +TArray savedModelFiles; TDeletingArray Models; TArray SpriteModelFrames; diff --git a/source/common/models/model.h b/source/common/models/model.h index 7e005a2d8..300661d25 100644 --- a/source/common/models/model.h +++ b/source/common/models/model.h @@ -12,6 +12,7 @@ struct FSpriteModelFrame; FTextureID LoadSkin(const char* path, const char* fn); void FlushModels(); +extern TArray savedModelFiles; extern TDeletingArray Models; extern TArray SpriteModelFrames; @@ -60,19 +61,15 @@ public: virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) = 0; virtual int FindFrame(const char * name) = 0; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0) = 0; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) = 0; virtual void BuildVertexBuffer(FModelRenderer *renderer) = 0; - virtual void AddSkins(uint8_t *hitlist) = 0; + virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) = 0; virtual float getAspectFactor(float vscale) { return 1.f; } void SetVertexBuffer(int type, IModelVertexBuffer *buffer) { mVBuf[type] = buffer; } IModelVertexBuffer *GetVertexBuffer(int type) const { return mVBuf[type]; } void DestroyVertexBuffer(); - const FSpriteModelFrame *curSpriteMDLFrame; - int curMDLIndex; - void PushSpriteMDLFrame(const FSpriteModelFrame *smf, int index) { curSpriteMDLFrame = smf; curMDLIndex = index; }; - FString mFileName; private: diff --git a/source/common/models/model_kvx.h b/source/common/models/model_kvx.h index 8d456d52c..4c107db5c 100644 --- a/source/common/models/model_kvx.h +++ b/source/common/models/model_kvx.h @@ -59,8 +59,8 @@ public: bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; void Initialize(); virtual int FindFrame(const char * name) override; - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0) override; - virtual void AddSkins(uint8_t *hitlist) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) override; + virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; FTextureID GetPaletteTexture() const { return mPalette; } void BuildVertexBuffer(FModelRenderer *renderer) override; float getAspectFactor(float vscale) override; diff --git a/source/common/models/model_md2.h b/source/common/models/model_md2.h index c04445535..966a38975 100644 --- a/source/common/models/model_md2.h +++ b/source/common/models/model_md2.h @@ -111,11 +111,11 @@ public: } virtual ~FDMDModel(); - virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length); - virtual int FindFrame(const char * name); - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0); + virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; + virtual int FindFrame(const char * name) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) override; virtual void LoadGeometry(); - virtual void AddSkins(uint8_t *hitlist); + virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; void UnloadGeometry(); void BuildVertexBuffer(FModelRenderer *renderer); diff --git a/source/common/models/model_md3.h b/source/common/models/model_md3.h index 3e6630a5a..e79a4c98b 100644 --- a/source/common/models/model_md3.h +++ b/source/common/models/model_md3.h @@ -65,11 +65,11 @@ class FMD3Model : public FModel public: FMD3Model() = default; - virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length); - virtual int FindFrame(const char * name); - virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0); + virtual bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; + virtual int FindFrame(const char * name) override; + virtual void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) override; void LoadGeometry(); void BuildVertexBuffer(FModelRenderer *renderer); - virtual void AddSkins(uint8_t *hitlist); + virtual void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; }; diff --git a/source/common/models/model_obj.h b/source/common/models/model_obj.h index ed190c1cd..a07090900 100644 --- a/source/common/models/model_obj.h +++ b/source/common/models/model_obj.h @@ -98,9 +98,9 @@ public: ~FOBJModel(); bool Load(const char* fn, int lumpnum, const char* buffer, int length) override; int FindFrame(const char* name) override; - void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation=0) override; + void RenderFrame(FModelRenderer* renderer, FGameTexture* skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) override; void BuildVertexBuffer(FModelRenderer* renderer) override; - void AddSkins(uint8_t* hitlist) override; + void AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) override; }; #endif diff --git a/source/common/models/model_ue1.h b/source/common/models/model_ue1.h index 967488355..2d29c2eff 100644 --- a/source/common/models/model_ue1.h +++ b/source/common/models/model_ue1.h @@ -26,9 +26,9 @@ public: bool Load(const char * fn, int lumpnum, const char * buffer, int length) override; int FindFrame(const char * name) override; - void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation=0) override; + void RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) override; void BuildVertexBuffer(FModelRenderer *renderer) override; - void AddSkins(uint8_t *hitlist) override; + void AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) override; void LoadGeometry(); void UnloadGeometry(); FUE1Model() diff --git a/source/common/models/models_md2.cpp b/source/common/models/models_md2.cpp index 8924392a4..f38472301 100644 --- a/source/common/models/models_md2.cpp +++ b/source/common/models/models_md2.cpp @@ -332,7 +332,7 @@ void FDMDModel::BuildVertexBuffer(FModelRenderer *renderer) // //=========================================================================== -void FDMDModel::AddSkins(uint8_t *hitlist) +void FDMDModel::AddSkins(uint8_t *hitlist, const FTextureID*) { for (int i = 0; i < info.numSkins; i++) { @@ -363,7 +363,7 @@ int FDMDModel::FindFrame(const char * name) // //=========================================================================== -void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation) +void FDMDModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID*) { if (frameno >= info.numFrames || frameno2 >= info.numFrames) return; diff --git a/source/common/models/models_md3.cpp b/source/common/models/models_md3.cpp index 0ec4d700f..29db7aa6f 100644 --- a/source/common/models/models_md3.cpp +++ b/source/common/models/models_md3.cpp @@ -302,14 +302,13 @@ void FMD3Model::BuildVertexBuffer(FModelRenderer *renderer) // //=========================================================================== -void FMD3Model::AddSkins(uint8_t *hitlist) +void FMD3Model::AddSkins(uint8_t *hitlist, const FTextureID* surfaceskinids) { for (unsigned i = 0; i < Surfaces.Size(); i++) { - int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + if (surfaceskinids && surfaceskinids[i].isValid()) { - hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[surfaceskinids[i].GetIndex()] |= FTextureManager::HIT_Flat; } MD3Surface * surf = &Surfaces[i]; @@ -344,7 +343,7 @@ int FMD3Model::FindFrame(const char * name) // //=========================================================================== -void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation) +void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids) { if ((unsigned)frameno >= Frames.Size() || (unsigned)frameno2 >= Frames.Size()) return; @@ -358,17 +357,13 @@ void FMD3Model::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f FGameTexture *surfaceSkin = skin; if (!surfaceSkin) { - if (curSpriteMDLFrame) + if (surfaceskinids && surfaceskinids[i].isValid()) { - int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) - { - surfaceSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); - } - else if (surf->numSkins > 0 && surf->Skins[0].isValid()) - { - surfaceSkin = TexMan.GetGameTexture(surf->Skins[0], true); - } + surfaceSkin = TexMan.GetGameTexture(surfaceskinids[i], true); + } + else if (surf->numSkins > 0 && surf->Skins[0].isValid()) + { + surfaceSkin = TexMan.GetGameTexture(surf->Skins[0], true); } if (!surfaceSkin) diff --git a/source/common/models/models_obj.cpp b/source/common/models/models_obj.cpp index 42fc6fd2a..5d4aefd3b 100644 --- a/source/common/models/models_obj.cpp +++ b/source/common/models/models_obj.cpp @@ -628,7 +628,7 @@ int FOBJModel::FindFrame(const char* name) * @param inter The amount to interpolate the two frames. * @param translation The translation for the skin */ -void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation) +void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frameno, int frameno2, double inter, int translation, const FTextureID* surfaceskinids) { // Prevent the model from rendering if the frame number is < 0 if (frameno < 0 || frameno2 < 0) return; @@ -638,12 +638,11 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f OBJSurface *surf = &surfaces[i]; FGameTexture *userSkin = skin; - if (!userSkin && curSpriteMDLFrame) + if (!userSkin) { - int ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + if (surfaceskinids && surfaceskinids[i].isValid()) { - userSkin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); + userSkin = TexMan.GetGameTexture(surfaceskinids[i], true); } else if (surf->skin.isValid()) { @@ -668,18 +667,17 @@ void FOBJModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int f * * @param hitlist The list of textures */ -void FOBJModel::AddSkins(uint8_t* hitlist) +void FOBJModel::AddSkins(uint8_t* hitlist, const FTextureID* surfaceskinids) { for (size_t i = 0; i < surfaces.Size(); i++) { - size_t ssIndex = i + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame && i < MD3_MAX_SURFACES && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) + if (surfaceskinids && i < MD3_MAX_SURFACES && surfaceskinids[i].isValid()) { // Precache skins manually reassigned by the user. // On OBJs with lots of skins, such as Doom map OBJs exported from GZDB, // there may be too many skins for the user to manually change, unless // the limit is bumped or surfaceskinIDs is changed to a TArray. - hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; + hitlist[surfaceskinids[i].GetIndex()] |= FTextureManager::HIT_Flat; return; // No need to precache skin that was replaced } diff --git a/source/common/models/models_ue1.cpp b/source/common/models/models_ue1.cpp index c7ffe88a9..f76f13eff 100644 --- a/source/common/models/models_ue1.cpp +++ b/source/common/models/models_ue1.cpp @@ -227,7 +227,7 @@ int FUE1Model::FindFrame( const char *name ) return -1; } -void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation ) +void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int frame, int frame2, double inter, int translation, const FTextureID* surfaceskinids) { // the moment of magic if ( (frame >= numFrames) || (frame2 >= numFrames) ) return; @@ -246,9 +246,8 @@ void FUE1Model::RenderFrame( FModelRenderer *renderer, FGameTexture *skin, int f FGameTexture *sskin = skin; if ( !sskin ) { - int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) - sskin = TexMan.GetGameTexture(curSpriteMDLFrame->surfaceskinIDs[ssIndex], true); + if (surfaceskinids && surfaceskinids[i].isValid()) + sskin = TexMan.GetGameTexture(surfaceskinids[i], true); if ( !sskin ) { vofs += vsize; @@ -305,13 +304,12 @@ void FUE1Model::BuildVertexBuffer( FModelRenderer *renderer ) vbuf->UnlockVertexBuffer(); } -void FUE1Model::AddSkins( uint8_t *hitlist ) +void FUE1Model::AddSkins( uint8_t *hitlist, const FTextureID* surfaceskinids) { for (int i = 0; i < numGroups; i++) { - int ssIndex = groups[i].texNum + curMDLIndex * MD3_MAX_SURFACES; - if (curSpriteMDLFrame && curSpriteMDLFrame->surfaceskinIDs[ssIndex].isValid()) - hitlist[curSpriteMDLFrame->surfaceskinIDs[ssIndex].GetIndex()] |= FTextureManager::HIT_Flat; + if (surfaceskinids && surfaceskinids[i].isValid()) + hitlist[surfaceskinids[i].GetIndex()] |= FTextureManager::HIT_Flat; } } diff --git a/source/common/models/models_voxel.cpp b/source/common/models/models_voxel.cpp index 50fc4df09..6db0c9e5f 100644 --- a/source/common/models/models_voxel.cpp +++ b/source/common/models/models_voxel.cpp @@ -356,7 +356,7 @@ void FVoxelModel::BuildVertexBuffer(FModelRenderer *renderer) // //=========================================================================== -void FVoxelModel::AddSkins(uint8_t *hitlist) +void FVoxelModel::AddSkins(uint8_t *hitlist, const FTextureID*) { hitlist[mPalette.GetIndex()] |= FTextureManager::HIT_Flat; } @@ -400,7 +400,7 @@ float FVoxelModel::getAspectFactor(float stretch) // //=========================================================================== -void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation) +void FVoxelModel::RenderFrame(FModelRenderer *renderer, FGameTexture * skin, int frame, int frame2, double inter, int translation, const FTextureID*) { renderer->SetMaterial(skin, true, translation); renderer->SetupFrame(this, 0, 0, 0); diff --git a/source/common/rendering/gl/gl_renderbuffers.cpp b/source/common/rendering/gl/gl_renderbuffers.cpp index 88d7bce42..4f49cdce3 100644 --- a/source/common/rendering/gl/gl_renderbuffers.cpp +++ b/source/common/rendering/gl/gl_renderbuffers.cpp @@ -87,6 +87,7 @@ void FGLRenderBuffers::ClearScene() void FGLRenderBuffers::ClearPipeline() { + DeleteRenderBuffer(mPipelineDepthStencilBuf); for (int i = 0; i < NumPipelineTextures; i++) { DeleteFrameBuffer(mPipelineFB[i]); @@ -239,10 +240,11 @@ void FGLRenderBuffers::CreatePipeline(int width, int height) ClearPipeline(); ClearEyeBuffers(); + mPipelineDepthStencilBuf = CreateRenderBuffer("PipelineDepthStencil", GL_DEPTH24_STENCIL8, width, height); for (int i = 0; i < NumPipelineTextures; i++) { mPipelineTexture[i] = Create2DTexture("PipelineTexture", GL_RGBA16F, width, height); - mPipelineFB[i] = CreateFrameBuffer("PipelineFB", mPipelineTexture[i]); + mPipelineFB[i] = CreateFrameBuffer("PipelineFB", mPipelineTexture[i], mPipelineDepthStencilBuf); } } @@ -990,4 +992,4 @@ int FGLRenderBuffers::NextEye(int eyeCount) return mCurrentEye; } -} // namespace OpenGLRenderer \ No newline at end of file +} // namespace OpenGLRenderer diff --git a/source/common/rendering/gl/gl_renderbuffers.h b/source/common/rendering/gl/gl_renderbuffers.h index da967f021..bb652e495 100644 --- a/source/common/rendering/gl/gl_renderbuffers.h +++ b/source/common/rendering/gl/gl_renderbuffers.h @@ -173,6 +173,7 @@ private: static const int NumPipelineTextures = 2; int mCurrentPipelineTexture = 0; + PPGLRenderBuffer mPipelineDepthStencilBuf; // Buffers for the scene PPGLTexture mSceneMultisampleTex; @@ -208,4 +209,4 @@ private: friend class GLPPRenderState; }; -} \ No newline at end of file +} diff --git a/source/common/rendering/hwrenderer/hw_draw2d.cpp b/source/common/rendering/hwrenderer/hw_draw2d.cpp index c54ba71d4..bd2691fbd 100644 --- a/source/common/rendering/hwrenderer/hw_draw2d.cpp +++ b/source/common/rendering/hwrenderer/hw_draw2d.cpp @@ -59,6 +59,9 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) state.SetViewport(mScreenViewport.left, mScreenViewport.top, mScreenViewport.width, mScreenViewport.height); 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.EnableMultisampling(false); state.EnableLineSmooth(gl_aalines); @@ -88,6 +91,22 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) 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.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); state.SetLightParms(0, 0); - state.AlphaFunc(Alpha_GEqual, 0.f); + state.AlphaFunc(Alpha_Greater, 0.f); if (cmd.useTransform) { @@ -225,6 +244,8 @@ void Draw2D(F2DDrawer *drawer, FRenderState &state) state.SetRenderStyle(STYLE_Translucent); state.SetVertexBuffer(screen->mVertexData); + state.EnableStencil(false); + state.SetStencil(0, SOP_Keep, SF_AllOn); state.EnableTexture(true); state.EnableBrightmap(true); state.SetTextureMode(TM_NORMAL); diff --git a/source/common/rendering/vulkan/renderer/vk_postprocess.cpp b/source/common/rendering/vulkan/renderer/vk_postprocess.cpp index 8c9834c39..0644a527f 100644 --- a/source/common/rendering/vulkan/renderer/vk_postprocess.cpp +++ b/source/common/rendering/vulkan/renderer/vk_postprocess.cpp @@ -57,9 +57,10 @@ void VkPostprocess::SetActiveRenderTarget() VkImageTransition() .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()); - 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 &afterBloomDrawEndScene2D) diff --git a/source/common/rendering/vulkan/renderer/vk_pprenderstate.cpp b/source/common/rendering/vulkan/renderer/vk_pprenderstate.cpp index 757f50350..3ef6d0251 100644 --- a/source/common/rendering/vulkan/renderer/vk_pprenderstate.cpp +++ b/source/common/rendering/vulkan/renderer/vk_pprenderstate.cpp @@ -71,12 +71,12 @@ void VkPPRenderState::Draw() if (Output.Type == PPTextureType::SceneColor) { - key.StencilTest = 1; + key.StencilTest = WhichDepthStencil::Scene; key.Samples = fb->GetBuffers()->GetSceneSamples(); } else { - key.StencilTest = 0; + key.StencilTest = WhichDepthStencil::None; key.Samples = VK_SAMPLE_COUNT_1_BIT; } @@ -86,7 +86,7 @@ void VkPPRenderState::Draw() VulkanDescriptorSet *input = fb->GetDescriptorSetManager()->GetInput(passSetup, Textures, ShadowMapBuffers); 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 if (Output.Type == PPTextureType::NextPipelineTexture) diff --git a/source/common/rendering/vulkan/renderer/vk_raytrace.cpp b/source/common/rendering/vulkan/renderer/vk_raytrace.cpp index d5ca0d6ee..3dd0cb0e3 100644 --- a/source/common/rendering/vulkan/renderer/vk_raytrace.cpp +++ b/source/common/rendering/vulkan/renderer/vk_raytrace.cpp @@ -24,7 +24,7 @@ #include "vulkan/system/vk_builders.h" #include "vulkan/system/vk_framebuffer.h" #include "vulkan/system/vk_commandbuffer.h" -//#include "doom_levelmesh.h" +#include "hw_levelmesh.h" VkRaytrace::VkRaytrace(VulkanFrameBuffer* fb) : fb(fb) { @@ -107,13 +107,21 @@ void VkRaytrace::CreateVertexAndIndexBuffers() transferBuffer->Unmap(); vertexBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Usage( + VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR) .Size(vertexbuffersize) .DebugName("vertexBuffer") .Create(fb->device); indexBuffer = BufferBuilder() - .Usage(VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) + .Usage( + VK_BUFFER_USAGE_INDEX_BUFFER_BIT | + VK_BUFFER_USAGE_TRANSFER_DST_BIT | + VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | + VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR) .Size(indexbuffersize) .DebugName("indexBuffer") .Create(fb->device); @@ -135,12 +143,6 @@ void VkRaytrace::CreateBottomLevelAccelerationStructure() VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {}; VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo }; - buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; - buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - buildInfo.geometryCount = 1; - buildInfo.ppGeometries = geometries; - accelStructBLDesc.geometryType = VK_GEOMETRY_TYPE_TRIANGLES_KHR; accelStructBLDesc.flags = VK_GEOMETRY_OPAQUE_BIT_KHR; accelStructBLDesc.geometry.triangles = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_TRIANGLES_DATA_KHR }; @@ -150,10 +152,14 @@ void VkRaytrace::CreateBottomLevelAccelerationStructure() accelStructBLDesc.geometry.triangles.indexType = VK_INDEX_TYPE_UINT32; accelStructBLDesc.geometry.triangles.indexData.deviceAddress = indexBuffer->GetDeviceAddress(); accelStructBLDesc.geometry.triangles.maxVertex = Mesh->MeshVertices.Size() - 1; - //accelStructBLDesc.geometry.triangles.transformData = transformAddress; // optional; VkTransformMatrixKHR transfered to a buffer? - rangeInfo.primitiveCount = Mesh->MeshElements.Size() / 3; - uint32_t maxPrimitiveCount = rangeInfo.primitiveCount; + buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; + buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; + buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; + buildInfo.geometryCount = 1; + buildInfo.ppGeometries = geometries; + + uint32_t maxPrimitiveCount = Mesh->MeshElements.Size() / 3; VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; vkGetAccelerationStructureBuildSizesKHR(fb->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxPrimitiveCount, &sizeInfo); @@ -164,16 +170,11 @@ void VkRaytrace::CreateBottomLevelAccelerationStructure() .DebugName("blAccelStructBuffer") .Create(fb->device); - VkAccelerationStructureKHR blAccelStructHandle = {}; - VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; - createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR; - createInfo.buffer = blAccelStructBuffer->buffer; - createInfo.size = sizeInfo.accelerationStructureSize; - VkResult result = vkCreateAccelerationStructureKHR(fb->device->device, &createInfo, nullptr, &blAccelStructHandle); - if (result != VK_SUCCESS) - throw std::runtime_error("vkCreateAccelerationStructureKHR failed"); - blAccelStruct = std::make_unique(fb->device, blAccelStructHandle); - blAccelStruct->SetDebugName("blAccelStruct"); + blAccelStruct = AccelerationStructureBuilder() + .Type(VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR) + .Buffer(blAccelStructBuffer.get(), sizeInfo.accelerationStructureSize) + .DebugName("blAccelStruct") + .Create(fb->device); blScratchBuffer = BufferBuilder() .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) @@ -183,6 +184,7 @@ void VkRaytrace::CreateBottomLevelAccelerationStructure() buildInfo.dstAccelerationStructure = blAccelStruct->accelstruct; buildInfo.scratchData.deviceAddress = blScratchBuffer->GetDeviceAddress(); + rangeInfo.primitiveCount = maxPrimitiveCount; fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos); @@ -221,10 +223,9 @@ void VkRaytrace::CreateTopLevelAccelerationStructure() fb->GetCommands()->GetTransferCommands()->copyBuffer(tlTransferBuffer.get(), tlInstanceBuffer.get()); // Finish transfering before using it as input - VkMemoryBarrier barrier = { VK_STRUCTURE_TYPE_MEMORY_BARRIER }; - barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT; - barrier.dstAccessMask = VK_ACCESS_ACCELERATION_STRUCTURE_READ_BIT_KHR; - fb->GetCommands()->GetTransferCommands()->pipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR, 0, 1, &barrier, 0, nullptr, 0, nullptr); + PipelineBarrier() + .AddMemory(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_SHADER_READ_BIT) + .Execute(fb->GetCommands()->GetTransferCommands(), VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ACCELERATION_STRUCTURE_BUILD_BIT_KHR); VkAccelerationStructureBuildGeometryInfoKHR buildInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_GEOMETRY_INFO_KHR }; VkAccelerationStructureGeometryKHR accelStructTLDesc = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_KHR }; @@ -232,19 +233,17 @@ void VkRaytrace::CreateTopLevelAccelerationStructure() VkAccelerationStructureBuildRangeInfoKHR rangeInfo = {}; VkAccelerationStructureBuildRangeInfoKHR* rangeInfos[] = { &rangeInfo }; + buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; + buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; buildInfo.flags = VK_BUILD_ACCELERATION_STRUCTURE_PREFER_FAST_TRACE_BIT_KHR; buildInfo.geometryCount = 1; buildInfo.ppGeometries = geometries; - buildInfo.mode = VK_BUILD_ACCELERATION_STRUCTURE_MODE_BUILD_KHR; - buildInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - buildInfo.srcAccelerationStructure = VK_NULL_HANDLE; accelStructTLDesc.geometryType = VK_GEOMETRY_TYPE_INSTANCES_KHR; accelStructTLDesc.geometry.instances = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_GEOMETRY_INSTANCES_DATA_KHR }; accelStructTLDesc.geometry.instances.data.deviceAddress = tlInstanceBuffer->GetDeviceAddress(); uint32_t maxInstanceCount = 1; - rangeInfo.primitiveCount = 1; VkAccelerationStructureBuildSizesInfoKHR sizeInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_BUILD_SIZES_INFO_KHR }; vkGetAccelerationStructureBuildSizesKHR(fb->device->device, VK_ACCELERATION_STRUCTURE_BUILD_TYPE_DEVICE_KHR, &buildInfo, &maxInstanceCount, &sizeInfo); @@ -255,15 +254,11 @@ void VkRaytrace::CreateTopLevelAccelerationStructure() .DebugName("tlAccelStructBuffer") .Create(fb->device); - VkAccelerationStructureKHR tlAccelStructHandle = {}; - VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; - createInfo.type = VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR; - createInfo.buffer = tlAccelStructBuffer->buffer; - createInfo.size = sizeInfo.accelerationStructureSize; - VkResult result = vkCreateAccelerationStructureKHR(fb->device->device, &createInfo, nullptr, &tlAccelStructHandle); - if (result != VK_SUCCESS) - throw std::runtime_error("vkCreateAccelerationStructureKHR failed"); - tlAccelStruct = std::make_unique(fb->device, tlAccelStructHandle); + tlAccelStruct = AccelerationStructureBuilder() + .Type(VK_ACCELERATION_STRUCTURE_TYPE_TOP_LEVEL_KHR) + .Buffer(tlAccelStructBuffer.get(), sizeInfo.accelerationStructureSize) + .DebugName("tlAccelStruct") + .Create(fb->device); tlScratchBuffer = BufferBuilder() .Usage(VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) @@ -273,6 +268,7 @@ void VkRaytrace::CreateTopLevelAccelerationStructure() buildInfo.dstAccelerationStructure = tlAccelStruct->accelstruct; buildInfo.scratchData.deviceAddress = tlScratchBuffer->GetDeviceAddress(); + rangeInfo.primitiveCount = 1; fb->GetCommands()->GetTransferCommands()->buildAccelerationStructures(1, &buildInfo, rangeInfos); diff --git a/source/common/rendering/vulkan/renderer/vk_renderpass.cpp b/source/common/rendering/vulkan/renderer/vk_renderpass.cpp index ea8d97b58..083745a91 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderpass.cpp +++ b/source/common/rendering/vulkan/renderer/vk_renderpass.cpp @@ -152,14 +152,14 @@ std::unique_ptr VkRenderPassSetup::CreateRenderPass(int clearT for (int i = 1; i < PassKey.DrawBuffers; i++) { builder.AddAttachment( - drawBufferFormats[i], buffers->GetSceneSamples(), + drawBufferFormats[i], (VkSampleCountFlagBits)PassKey.Samples, (clearTargets & CT_Color) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); } if (PassKey.DepthStencil) { builder.AddDepthStencilAttachment( - buffers->SceneDepthStencilFormat, PassKey.DrawBufferFormat == VK_FORMAT_R8G8B8A8_UNORM ? VK_SAMPLE_COUNT_1_BIT : buffers->GetSceneSamples(), + buffers->SceneDepthStencilFormat, (VkSampleCountFlagBits)PassKey.Samples, (clearTargets & CT_Depth) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, (clearTargets & CT_Stencil) ? VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD, VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); @@ -342,7 +342,7 @@ void VkPPRenderPassSetup::CreatePipeline(const VkPPRenderPassKey& key) // Note: the actual values are ignored since we use dynamic viewport+scissor states builder.Viewport(0.0f, 0.0f, 320.0f, 200.0f); builder.Scissor(0, 0, 320, 200); - if (key.StencilTest) + if (key.StencilTest != WhichDepthStencil::None) { builder.AddDynamicState(VK_DYNAMIC_STATE_STENCIL_REFERENCE); 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); 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); - if (key.StencilTest) + if (key.StencilTest == WhichDepthStencil::Scene) { builder.AddDepthStencilAttachment( 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_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.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.AddExternalSubpassDependency( diff --git a/source/common/rendering/vulkan/renderer/vk_renderpass.h b/source/common/rendering/vulkan/renderer/vk_renderpass.h index c1957871d..06cb47992 100644 --- a/source/common/rendering/vulkan/renderer/vk_renderpass.h +++ b/source/common/rendering/vulkan/renderer/vk_renderpass.h @@ -78,6 +78,8 @@ public: int UseVertexData; }; +enum class WhichDepthStencil; + class VkPPRenderPassKey { public: @@ -88,7 +90,7 @@ public: VkFormat OutputFormat; int SwapChain; int ShadowMapBuffers; - int StencilTest; + WhichDepthStencil StencilTest; VkSampleCountFlagBits Samples; bool operator<(const VkPPRenderPassKey& other) const { return memcmp(this, &other, sizeof(VkPPRenderPassKey)) < 0; } diff --git a/source/common/rendering/vulkan/system/vk_builders.cpp b/source/common/rendering/vulkan/system/vk_builders.cpp index b2bc2a42c..aff0de50a 100644 --- a/source/common/rendering/vulkan/system/vk_builders.cpp +++ b/source/common/rendering/vulkan/system/vk_builders.cpp @@ -545,6 +545,46 @@ std::unique_ptr BufferBuilder::Create(VulkanDevice* device) ///////////////////////////////////////////////////////////////////////////// +AccelerationStructureBuilder::AccelerationStructureBuilder() +{ +} + +AccelerationStructureBuilder& AccelerationStructureBuilder::Type(VkAccelerationStructureTypeKHR type) +{ + createInfo.type = type; + return *this; +} + +AccelerationStructureBuilder& AccelerationStructureBuilder::Buffer(VulkanBuffer* buffer, VkDeviceSize size) +{ + createInfo.buffer = buffer->buffer; + createInfo.offset = 0; + createInfo.size = size; + return *this; +} + +AccelerationStructureBuilder& AccelerationStructureBuilder::Buffer(VulkanBuffer* buffer, VkDeviceSize offset, VkDeviceSize size) +{ + createInfo.buffer = buffer->buffer; + createInfo.offset = offset; + createInfo.size = size; + return *this; +} + +std::unique_ptr AccelerationStructureBuilder::Create(VulkanDevice* device) +{ + VkAccelerationStructureKHR hande = {}; + VkResult result = vkCreateAccelerationStructureKHR(device->device, &createInfo, nullptr, &hande); + if (result != VK_SUCCESS) + throw std::runtime_error("vkCreateAccelerationStructureKHR failed"); + auto obj = std::make_unique(device, hande); + if (debugName) + obj->SetDebugName(debugName); + return obj; +} + +///////////////////////////////////////////////////////////////////////////// + ComputePipelineBuilder::ComputePipelineBuilder() { pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; diff --git a/source/common/rendering/vulkan/system/vk_builders.h b/source/common/rendering/vulkan/system/vk_builders.h index 2f47942cb..db3528bb5 100644 --- a/source/common/rendering/vulkan/system/vk_builders.h +++ b/source/common/rendering/vulkan/system/vk_builders.h @@ -100,6 +100,23 @@ private: const char* debugName = nullptr; }; +class AccelerationStructureBuilder +{ +public: + AccelerationStructureBuilder(); + + AccelerationStructureBuilder& Type(VkAccelerationStructureTypeKHR type); + AccelerationStructureBuilder& Buffer(VulkanBuffer* buffer, VkDeviceSize size); + AccelerationStructureBuilder& Buffer(VulkanBuffer* buffer, VkDeviceSize offset, VkDeviceSize size); + AccelerationStructureBuilder& DebugName(const char* name) { debugName = name; return *this; } + + std::unique_ptr Create(VulkanDevice* device); + +private: + VkAccelerationStructureCreateInfoKHR createInfo = { VK_STRUCTURE_TYPE_ACCELERATION_STRUCTURE_CREATE_INFO_KHR }; + const char* debugName = nullptr; +}; + class ComputePipelineBuilder { public: diff --git a/source/common/rendering/vulkan/textures/vk_renderbuffers.cpp b/source/common/rendering/vulkan/textures/vk_renderbuffers.cpp index aa49b0fde..16f0fe782 100644 --- a/source/common/rendering/vulkan/textures/vk_renderbuffers.cpp +++ b/source/common/rendering/vulkan/textures/vk_renderbuffers.cpp @@ -83,14 +83,49 @@ void VkRenderBuffers::BeginFrame(int width, int height, int sceneWidth, int scen 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) { for (int i = 0; i < NumPipelineImages; i++) { PipelineImage[i].Reset(fb); } + PipelineDepthStencil.Reset(fb); + + CreatePipelineDepthStencil(width, height); VkImageTransition barrier; + barrier.AddImage(&PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, true); for (int i = 0; i < NumPipelineImages; i++) { PipelineImage[i].Image = ImageBuilder() @@ -216,7 +251,7 @@ void VkRenderBuffers::CreateSceneNormal(int width, int height, VkSampleCountFlag .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); @@ -227,8 +262,12 @@ VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, co { VkImageTransition imageTransition; 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); + + if (stencilTest == WhichDepthStencil::Pipeline) + imageTransition.AddImage(&fb->GetBuffers()->PipelineDepthStencil, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, false); + imageTransition.Execute(fb->GetCommands()->GetDrawCommands()); view = tex->View->view; @@ -251,8 +290,10 @@ VulkanFramebuffer* VkRenderBuffers::GetOutput(VkPPRenderPassSetup* passSetup, co builder.RenderPass(passSetup->RenderPass.get()); builder.Size(w, h); builder.AddAttachment(view); - if (stencilTest) + if (stencilTest == WhichDepthStencil::Scene) builder.AddAttachment(fb->GetBuffers()->SceneDepthStencil.View.get()); + if (stencilTest == WhichDepthStencil::Pipeline) + builder.AddAttachment(fb->GetBuffers()->PipelineDepthStencil.View.get()); builder.DebugName("PPOutputFB"); framebuffer = builder.Create(fb->device); } diff --git a/source/common/rendering/vulkan/textures/vk_renderbuffers.h b/source/common/rendering/vulkan/textures/vk_renderbuffers.h index 04d5667d5..52d425896 100644 --- a/source/common/rendering/vulkan/textures/vk_renderbuffers.h +++ b/source/common/rendering/vulkan/textures/vk_renderbuffers.h @@ -8,6 +8,12 @@ class VulkanFrameBuffer; class VkPPRenderPassSetup; class PPOutput; +enum class WhichDepthStencil { + None, + Scene, + Pipeline, +}; + class VkRenderBuffers { public: @@ -27,15 +33,18 @@ public: VkTextureImage SceneNormal; VkTextureImage SceneFog; + VkFormat PipelineDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; VkFormat SceneDepthStencilFormat = VK_FORMAT_D24_UNORM_S8_UINT; VkFormat SceneNormalFormat = VK_FORMAT_A2R10G10B10_UNORM_PACK32; static const int NumPipelineImages = 2; + VkTextureImage PipelineDepthStencil; 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: + void CreatePipelineDepthStencil(int width, int height); void CreatePipeline(int width, int height); void CreateScene(int width, int height, VkSampleCountFlagBits samples); void CreateSceneColor(int width, int height, VkSampleCountFlagBits samples); diff --git a/source/core/rendering/scene/hw_sprites.cpp b/source/core/rendering/scene/hw_sprites.cpp index 392418a3d..b855d4756 100644 --- a/source/core/rendering/scene/hw_sprites.cpp +++ b/source/core/rendering/scene/hw_sprites.cpp @@ -154,7 +154,7 @@ void HWSprite::DrawSprite(HWDrawInfo* di, FRenderState& state, bool translucent) bool mirrored = ((Sprite->cstat & CSTAT_SPRITE_XFLIP) != 0) ^ ((Sprite->cstat & CSTAT_SPRITE_YFLIP) != 0) ^ portalState.isMirrored(); mr.BeginDrawModel(RenderStyle, nullptr, rotmat, mirrored); mr.SetupFrame(model, 0, 0, 0); - model->RenderFrame(&mr, TexMan.GetGameTexture(model->GetPaletteTexture()), 0, 0, 0.f, TRANSLATION(Translation_Remap + curbasepal, palette)); + model->RenderFrame(&mr, TexMan.GetGameTexture(model->GetPaletteTexture()), 0, 0, 0.f, TRANSLATION(Translation_Remap + curbasepal, palette), nullptr); mr.EndDrawModel(RenderStyle, nullptr); state.SetDepthFunc(DF_Less); state.SetVertexBuffer(screen->mVertexData); diff --git a/source/glbackend/glbackend.cpp b/source/glbackend/glbackend.cpp index 144eba78d..436522e37 100644 --- a/source/glbackend/glbackend.cpp +++ b/source/glbackend/glbackend.cpp @@ -119,7 +119,7 @@ void GLInstance::DoDraw() state.EnableTexture(true); rs.model->BuildVertexBuffer(&mr); mr.SetupFrame(rs.model, rs.mframes[0], rs.mframes[1], 0); - rs.model->RenderFrame(&mr, rs.mMaterial.mTexture, rs.mframes[0], rs.mframes[1], 0.f, rs.mMaterial.mTranslation); + rs.model->RenderFrame(&mr, rs.mMaterial.mTexture, rs.mframes[0], rs.mframes[1], 0.f, rs.mMaterial.mTranslation, nullptr); state.SetDepthFunc(DF_Less); state.SetVertexBuffer(screen->mVertexData); } diff --git a/wadsrc/static/zscript/engine/base.zs b/wadsrc/static/zscript/engine/base.zs index 45e178af0..f6650c297 100644 --- a/wadsrc/static/zscript/engine/base.zs +++ b/wadsrc/static/zscript/engine/base.zs @@ -464,12 +464,26 @@ 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 { native void Clear(); native void Rotate(double angle); native void Scale(Vector2 scaleVec); native void Translate(Vector2 translateVec); + native void From2D(double m00, double m01, double m10, double m11, double vx, double vy); } class Shape2D : Object native @@ -500,6 +514,7 @@ struct Screen native native static vararg void DrawTexture(TextureID tex, bool animate, double x, double y, ...); native static vararg void DrawShape(TextureID tex, bool animate, Shape2D s, ...); + native static vararg void DrawShapeFill(Color col, double amount, Shape2D s, ...); native static vararg void DrawChar(Font font, int normalcolor, double x, double y, int character, ...); native static vararg void DrawText(Font font, int normalcolor, double x, double y, String text, ...); native static void DrawLine(int x0, int y0, int x1, int y1, Color color, int alpha = 255); @@ -515,6 +530,12 @@ struct Screen native native static Vector2 SetOffset(double x, double y); native static void ClearScreen(color col = 0); 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 ClearTransform(); } struct Font native diff --git a/wadsrc/static/zscript/engine/screenjob.zs b/wadsrc/static/zscript/engine/screenjob.zs index c65091c6e..51940f7e8 100644 --- a/wadsrc/static/zscript/engine/screenjob.zs +++ b/wadsrc/static/zscript/engine/screenjob.zs @@ -9,6 +9,7 @@ class ScreenJob : Object UI int jobstate; bool skipover; + bool nowipe; enum EJobState { @@ -229,6 +230,7 @@ class MoviePlayerJob : SkippableScreenJob Super.Init(); flag = flags; player = mp; + nowipe = true; // due to synchronization issues wipes must be disabled on any movie. return self; } @@ -360,6 +362,12 @@ class ScreenJobRunner : Object UI return jobs.Size() > 0; } + bool CanWipe() + { + if (index < jobs.Size()) return !jobs[index].nowipe; + return true; + } + //--------------------------------------------------------------------------- // //