diff --git a/src/rendering/polyrenderer/backend/poly_buffers.cpp b/src/rendering/polyrenderer/backend/poly_buffers.cpp index 7ca4d1768..fd0ead6ea 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.cpp +++ b/src/rendering/polyrenderer/backend/poly_buffers.cpp @@ -18,6 +18,10 @@ PolyBuffer::~PolyBuffer() if (Next) Next->Prev = Prev; if (Prev) Prev->Next = Next; else First = Next; + + auto fb = GetPolyFrameBuffer(); + if (fb && !mData.empty()) + fb->FrameDeleteList.Buffers.push_back(std::move(mData)); } void PolyBuffer::ResetAll() @@ -79,43 +83,29 @@ void PolyVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t mStride = stride; } -void PolyVertexBuffer::CopyVertices(TriVertex *dst, int count, int index) +ShadedTriVertex PolyVertexBuffer::Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) { - size_t stride = mStride; - size_t offsetVertex = mOffsets[VATTR_VERTEX]; - size_t offsetTexcoord = mOffsets[VATTR_TEXCOORD]; - uint8_t *vertex = static_cast(map) + stride * index; + const uint8_t *vertex = static_cast(vertices) + mStride * index; + const float *attrVertex = reinterpret_cast(vertex + mOffsets[VATTR_VERTEX]); + const float *attrTexcoord = reinterpret_cast(vertex + mOffsets[VATTR_TEXCOORD]); - for (int i = 0; i < count; i++) - { - dst[i].x = *reinterpret_cast(vertex + offsetVertex); - dst[i].y = *reinterpret_cast(vertex + offsetVertex + 4); - dst[i].z = *reinterpret_cast(vertex + offsetVertex + 8); - dst[i].w = 1.0f; - dst[i].v = *reinterpret_cast(vertex + offsetTexcoord); - dst[i].u = *reinterpret_cast(vertex + offsetTexcoord + 4); - vertex += stride; - } -} + Vec4f objpos = Vec4f(attrVertex[0], attrVertex[1], attrVertex[2], 1.0f); + Vec4f clippos = (*thread->objectToClip) * objpos; -void PolyVertexBuffer::CopyIndexed(TriVertex *dst, uint32_t *elements, int count, int index) -{ - size_t stride = mStride; - size_t offsetVertex = mOffsets[VATTR_VERTEX]; - size_t offsetTexcoord = mOffsets[VATTR_TEXCOORD]; - uint8_t *vertices = static_cast(map); - - elements += index; - for (int i = 0; i < count; i++) - { - uint8_t *vertex = vertices + stride * elements[i]; - dst[i].x = *reinterpret_cast(vertex + offsetVertex); - dst[i].y = *reinterpret_cast(vertex + offsetVertex + 4); - dst[i].z = *reinterpret_cast(vertex + offsetVertex + 8); - dst[i].w = 1.0f; - dst[i].v = *reinterpret_cast(vertex + offsetTexcoord); - dst[i].u = *reinterpret_cast(vertex + offsetTexcoord + 4); - } + ShadedTriVertex sv; + sv.u = attrTexcoord[1]; + sv.v = attrTexcoord[0]; + sv.x = clippos.X; + sv.y = clippos.Y; + sv.z = clippos.Z; + sv.w = clippos.W; + sv.worldX = objpos.X; + sv.worldY = objpos.Y; + sv.worldZ = objpos.Z; + sv.clipDistance[0] = 1.0f; + sv.clipDistance[1] = 1.0f; + sv.clipDistance[2] = 1.0f; + return sv; } ///////////////////////////////////////////////////////////////////////////// diff --git a/src/rendering/polyrenderer/backend/poly_buffers.h b/src/rendering/polyrenderer/backend/poly_buffers.h index 49375c7d0..2ad9e11f9 100644 --- a/src/rendering/polyrenderer/backend/poly_buffers.h +++ b/src/rendering/polyrenderer/backend/poly_buffers.h @@ -1,6 +1,7 @@ #pragma once #include "hwrenderer/data/buffers.h" +#include "polyrenderer/drawers/poly_triangle.h" #include "utility/tarray.h" #include @@ -38,14 +39,13 @@ private: std::vector mData; }; -class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer +class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer, public PolyVertexShader { public: PolyVertexBuffer() { } void SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs) override; - void CopyVertices(TriVertex *dst, int count, int index); - void CopyIndexed(TriVertex *dst, uint32_t *elements, int count, int index); + ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) override; private: size_t mOffsets[VATTR_MAX] = {}; diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp index 513936d3e..4131acae9 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.cpp +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.cpp @@ -141,6 +141,7 @@ void PolyFrameBuffer::Update() FlushDrawCommands(); DrawerThreads::WaitForWorkers(); mFrameMemory.Clear(); + FrameDeleteList.Buffers.clear(); if (mCanvas) { diff --git a/src/rendering/polyrenderer/backend/poly_framebuffer.h b/src/rendering/polyrenderer/backend/poly_framebuffer.h index 11cff6a2c..e56318145 100644 --- a/src/rendering/polyrenderer/backend/poly_framebuffer.h +++ b/src/rendering/polyrenderer/backend/poly_framebuffer.h @@ -59,6 +59,11 @@ public: void SetVSync(bool vsync) override; void Draw2D() override; + struct DeleteList + { + std::vector> Buffers; + } FrameDeleteList; + private: sector_t *RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen); void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV); diff --git a/src/rendering/polyrenderer/backend/poly_renderstate.cpp b/src/rendering/polyrenderer/backend/poly_renderstate.cpp index bbe19b047..ea1148d1a 100644 --- a/src/rendering/polyrenderer/backend/poly_renderstate.cpp +++ b/src/rendering/polyrenderer/backend/poly_renderstate.cpp @@ -41,10 +41,7 @@ void PolyRenderState::Draw(int dt, int index, int count, bool apply) if (apply) Apply(); - auto fb = GetPolyFrameBuffer(); - TriVertex *vertices = fb->GetFrameMemory()->AllocMemory(count); - static_cast(mVertexBuffer)->CopyVertices(vertices, count, index); - PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]); + PolyTriangleDrawer::Draw(GetPolyFrameBuffer()->GetDrawCommands(), index, count, dtToDrawMode[dt]); } void PolyRenderState::DrawIndexed(int dt, int index, int count, bool apply) @@ -52,10 +49,7 @@ void PolyRenderState::DrawIndexed(int dt, int index, int count, bool apply) if (apply) Apply(); - auto fb = GetPolyFrameBuffer(); - TriVertex *vertices = fb->GetFrameMemory()->AllocMemory(count); - static_cast(mVertexBuffer)->CopyIndexed(vertices, (uint32_t *)mIndexBuffer->Memory(), count, index); - PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]); + PolyTriangleDrawer::DrawIndexed(GetPolyFrameBuffer()->GetDrawCommands(), index, count, dtToDrawMode[dt]); } bool PolyRenderState::SetDepthClamp(bool on) @@ -179,7 +173,11 @@ void PolyRenderState::Apply() } auto fb = GetPolyFrameBuffer(); + if (mVertexBuffer) PolyTriangleDrawer::SetVertexBuffer(fb->GetDrawCommands(), mVertexBuffer->Memory()); + if (mIndexBuffer) PolyTriangleDrawer::SetIndexBuffer(fb->GetDrawCommands(), mIndexBuffer->Memory()); + PolyTriangleDrawer::SetVertexShader(fb->GetDrawCommands(), static_cast(mVertexBuffer)); PolyTriangleDrawer::SetTwoSided(fb->GetDrawCommands(), true); + PolyTriangleDrawer::PushConstants(fb->GetDrawCommands(), args); drawcalls.Unclock(); } diff --git a/src/rendering/polyrenderer/drawers/poly_buffer.h b/src/rendering/polyrenderer/drawers/poly_buffer.h index 160aa1067..14ffd5063 100644 --- a/src/rendering/polyrenderer/drawers/poly_buffer.h +++ b/src/rendering/polyrenderer/drawers/poly_buffer.h @@ -24,8 +24,6 @@ #include -struct TriVertex; - class PolyZBuffer { public: diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.cpp b/src/rendering/polyrenderer/drawers/poly_triangle.cpp index 564c0f6f8..14d3972e1 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.cpp +++ b/src/rendering/polyrenderer/drawers/poly_triangle.cpp @@ -86,6 +86,11 @@ void PolyTriangleDrawer::SetViewport(const DrawerCommandQueuePtr &queue, int x, queue->Push(viewport_x, viewport_y, viewport_width, viewport_height, dest, dest_width, dest_height, dest_pitch, dest_bgra); } +void PolyTriangleDrawer::SetVertexShader(const DrawerCommandQueuePtr &queue, PolyVertexShader *shader) +{ + queue->Push(shader); +} + void PolyTriangleDrawer::SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld) { queue->Push(objectToClip, objectToWorld); @@ -111,14 +116,29 @@ void PolyTriangleDrawer::SetModelVertexShader(const DrawerCommandQueuePtr &queue queue->Push(frame1, frame2, interpolationFactor); } -void PolyTriangleDrawer::DrawArray(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, int vcount, PolyDrawMode mode) +void PolyTriangleDrawer::SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices) { - queue->Push(args, vertices, nullptr, vcount, mode); + queue->Push(vertices); } -void PolyTriangleDrawer::DrawElements(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode) +void PolyTriangleDrawer::SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements) { - queue->Push(args, vertices, elements, count, mode); + queue->Push(elements); +} + +void PolyTriangleDrawer::PushConstants(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args) +{ + queue->Push(args); +} + +void PolyTriangleDrawer::Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode) +{ + queue->Push(index, vcount, mode); +} + +void PolyTriangleDrawer::DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode) +{ + queue->Push(index, count, mode); } ///////////////////////////////////////////////////////////////////////////// @@ -181,11 +201,18 @@ void PolyTriangleThreadData::SetTransform(const Mat4f *newObjectToClip, const Ma objectToWorld = newObjectToWorld; } -void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const void *vertices, const unsigned int *elements, int vcount, PolyDrawMode drawmode) +void PolyTriangleThreadData::PushConstants(const PolyDrawArgs &args) +{ + drawargs = args; +} + +void PolyTriangleThreadData::DrawIndexed(int index, int vcount, PolyDrawMode drawmode) { if (vcount < 3) return; + elements += index; + TriDrawTriangleArgs args; args.uniforms = &drawargs; @@ -195,17 +222,17 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[j] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); DrawShadedTriangle(vert, ccw, &args); } } else if (drawmode == PolyDrawMode::TriangleFan) { - vert[0] = ShadeVertex(drawargs, vertices, *(elements++)); - vert[1] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[0] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + vert[1] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[2] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } @@ -213,11 +240,11 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = ShadeVertex(drawargs, vertices, *(elements++)); - vert[1] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[0] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); + vert[1] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, *(elements++)); + vert[2] = vertexShader->Shade(this, drawargs, vertices, *(elements++)); DrawShadedTriangle(vert, toggleccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; @@ -226,7 +253,7 @@ void PolyTriangleThreadData::DrawElements(const PolyDrawArgs &drawargs, const vo } } -void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void *vertices, int vcount, PolyDrawMode drawmode) +void PolyTriangleThreadData::Draw(int index, int vcount, PolyDrawMode drawmode) { if (vcount < 3) return; @@ -234,7 +261,7 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void TriDrawTriangleArgs args; args.uniforms = &drawargs; - int vinput = 0; + int vinput = index; ShadedTriVertex vert[3]; if (drawmode == PolyDrawMode::Triangles) @@ -242,17 +269,17 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void for (int i = 0; i < vcount / 3; i++) { for (int j = 0; j < 3; j++) - vert[j] = ShadeVertex(drawargs, vertices, vinput++); + vert[j] = vertexShader->Shade(this, drawargs, vertices, vinput++); DrawShadedTriangle(vert, ccw, &args); } } else if (drawmode == PolyDrawMode::TriangleFan) { - vert[0] = ShadeVertex(drawargs, vertices, vinput++); - vert[1] = ShadeVertex(drawargs, vertices, vinput++); + vert[0] = vertexShader->Shade(this, drawargs, vertices, vinput++); + vert[1] = vertexShader->Shade(this, drawargs, vertices, vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, vinput++); + vert[2] = vertexShader->Shade(this, drawargs, vertices, vinput++); DrawShadedTriangle(vert, ccw, &args); vert[1] = vert[2]; } @@ -260,11 +287,11 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void else // TriangleDrawMode::TriangleStrip { bool toggleccw = ccw; - vert[0] = ShadeVertex(drawargs, vertices, vinput++); - vert[1] = ShadeVertex(drawargs, vertices, vinput++); + vert[0] = vertexShader->Shade(this, drawargs, vertices, vinput++); + vert[1] = vertexShader->Shade(this, drawargs, vertices, vinput++); for (int i = 2; i < vcount; i++) { - vert[2] = ShadeVertex(drawargs, vertices, vinput++); + vert[2] = vertexShader->Shade(this, drawargs, vertices, vinput++); DrawShadedTriangle(vert, toggleccw, &args); vert[0] = vert[1]; vert[1] = vert[2]; @@ -273,31 +300,31 @@ void PolyTriangleThreadData::DrawArray(const PolyDrawArgs &drawargs, const void } } -ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs, const void *vertices, int index) +ShadedTriVertex PolyTriVertexShader::Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) { ShadedTriVertex sv; Vec4f objpos; - if (modelFrame1 == -1) + if (thread->modelFrame1 == -1) { const TriVertex &v = static_cast(vertices)[index]; objpos = Vec4f(v.x, v.y, v.z, v.w); sv.u = v.u; sv.v = v.v; } - else if (modelFrame1 == modelFrame2 || modelInterpolationFactor == 0.f) + else if (thread->modelFrame1 == thread->modelFrame2 || thread->modelInterpolationFactor == 0.f) { - const FModelVertex &v = static_cast(vertices)[modelFrame1 + index]; + const FModelVertex &v = static_cast(vertices)[thread->modelFrame1 + index]; objpos = Vec4f(v.x, v.y, v.z, 1.0f); sv.u = v.u; sv.v = v.v; } else { - const FModelVertex &v1 = static_cast(vertices)[modelFrame1 + index]; - const FModelVertex &v2 = static_cast(vertices)[modelFrame2 + index]; + const FModelVertex &v1 = static_cast(vertices)[thread->modelFrame1 + index]; + const FModelVertex &v2 = static_cast(vertices)[thread->modelFrame2 + index]; - float frac = modelInterpolationFactor; + float frac = thread->modelInterpolationFactor; float inv_frac = 1.0f - frac; objpos = Vec4f(v1.x * inv_frac + v2.x * frac, v1.y * inv_frac + v2.y * frac, v1.z * inv_frac + v2.z * frac, 1.0f); @@ -306,14 +333,14 @@ ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs } // Apply transform to get clip coordinates: - Vec4f clippos = (*objectToClip) * objpos; + Vec4f clippos = (*thread->objectToClip) * objpos; sv.x = clippos.X; sv.y = clippos.Y; sv.z = clippos.Z; sv.w = clippos.W; - if (!objectToWorld) // Identity matrix + if (!thread->objectToWorld) // Identity matrix { sv.worldX = objpos.X; sv.worldY = objpos.Y; @@ -321,7 +348,7 @@ ShadedTriVertex PolyTriangleThreadData::ShadeVertex(const PolyDrawArgs &drawargs } else { - Vec4f worldpos = (*objectToWorld) * objpos; + Vec4f worldpos = (*thread->objectToWorld) * objpos; sv.worldX = worldpos.X; sv.worldY = worldpos.Y; sv.worldZ = worldpos.Z; @@ -655,6 +682,39 @@ PolyTriangleThreadData *PolyTriangleThreadData::Get(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// +PolySetVertexBufferCommand::PolySetVertexBufferCommand(const void *vertices) : vertices(vertices) +{ +} + +void PolySetVertexBufferCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetVertexBuffer(vertices); +} + +///////////////////////////////////////////////////////////////////////////// + +PolySetIndexBufferCommand::PolySetIndexBufferCommand(const void *indices) : indices(indices) +{ +} + +void PolySetIndexBufferCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetIndexBuffer(indices); +} + +///////////////////////////////////////////////////////////////////////////// + +PolySetVertexShaderCommand::PolySetVertexShaderCommand(PolyVertexShader *shader) : shader(shader) +{ +} + +void PolySetVertexShaderCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->SetVertexShader(shader); +} + +///////////////////////////////////////////////////////////////////////////// + PolySetTransformCommand::PolySetTransformCommand(const Mat4f *objectToClip, const Mat4f *objectToWorld) : objectToClip(objectToClip), objectToWorld(objectToWorld) { } @@ -744,32 +804,33 @@ void PolySetViewportCommand::Execute(DrawerThread *thread) ///////////////////////////////////////////////////////////////////////////// -DrawPolyTrianglesCommand::DrawPolyTrianglesCommand(const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode) : args(args), vertices(vertices), elements(elements), count(count), mode(mode) +PolyPushConstantsCommand::PolyPushConstantsCommand(const PolyDrawArgs &args) : args(args) { } -void DrawPolyTrianglesCommand::Execute(DrawerThread *thread) +void PolyPushConstantsCommand::Execute(DrawerThread *thread) { - if (!elements) - PolyTriangleThreadData::Get(thread)->DrawArray(args, vertices, count, mode); - else - PolyTriangleThreadData::Get(thread)->DrawElements(args, vertices, elements, count, mode); + PolyTriangleThreadData::Get(thread)->PushConstants(args); } ///////////////////////////////////////////////////////////////////////////// -#if 0 -void DrawRectCommand::Execute(DrawerThread *thread) +PolyDrawCommand::PolyDrawCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) { - auto renderTarget = PolyRenderer::Instance()->RenderTarget; - const void *destOrg = renderTarget->GetPixels(); - int destWidth = renderTarget->GetWidth(); - int destHeight = renderTarget->GetHeight(); - int destPitch = renderTarget->GetPitch(); - int blendmode = (int)args.BlendMode(); - if (renderTarget->IsBgra()) - ScreenTriangle::RectDrawers32[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread)); - else - ScreenTriangle::RectDrawers8[blendmode](destOrg, destWidth, destHeight, destPitch, &args, PolyTriangleThreadData::Get(thread)); } -#endif + +void PolyDrawCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->Draw(index, count, mode); +} + +///////////////////////////////////////////////////////////////////////////// + +PolyDrawIndexedCommand::PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode) : index(index), count(count), mode(mode) +{ +} + +void PolyDrawIndexedCommand::Execute(DrawerThread *thread) +{ + PolyTriangleThreadData::Get(thread)->DrawIndexed(index, count, mode); +} diff --git a/src/rendering/polyrenderer/drawers/poly_triangle.h b/src/rendering/polyrenderer/drawers/poly_triangle.h index 10b17f067..3751d24c8 100644 --- a/src/rendering/polyrenderer/drawers/poly_triangle.h +++ b/src/rendering/polyrenderer/drawers/poly_triangle.h @@ -31,6 +31,7 @@ class DCanvas; class PolyDrawerCommand; +class PolyVertexShader; class PolyTriangleDrawer { @@ -39,16 +40,32 @@ public: static void ClearDepth(const DrawerCommandQueuePtr &queue, float value); static void ClearStencil(const DrawerCommandQueuePtr &queue, uint8_t value); static void SetViewport(const DrawerCommandQueuePtr &queue, int x, int y, int width, int height, DCanvas *canvas); + static void SetVertexShader(const DrawerCommandQueuePtr &queue, PolyVertexShader *shader); static void SetCullCCW(const DrawerCommandQueuePtr &queue, bool ccw); static void SetTwoSided(const DrawerCommandQueuePtr &queue, bool twosided); static void SetWeaponScene(const DrawerCommandQueuePtr &queue, bool enable); static void SetModelVertexShader(const DrawerCommandQueuePtr &queue, int frame1, int frame2, float interpolationFactor); static void SetTransform(const DrawerCommandQueuePtr &queue, const Mat4f *objectToClip, const Mat4f *objectToWorld); - static void DrawArray(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); - static void DrawElements(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode = PolyDrawMode::Triangles); + static void SetVertexBuffer(const DrawerCommandQueuePtr &queue, const void *vertices); + static void SetIndexBuffer(const DrawerCommandQueuePtr &queue, const void *elements); + static void PushConstants(const DrawerCommandQueuePtr &queue, const PolyDrawArgs &args); + static void Draw(const DrawerCommandQueuePtr &queue, int index, int vcount, PolyDrawMode mode = PolyDrawMode::Triangles); + static void DrawIndexed(const DrawerCommandQueuePtr &queue, int index, int count, PolyDrawMode mode = PolyDrawMode::Triangles); static bool IsBgra(); }; +class PolyVertexShader +{ +public: + virtual ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) = 0; +}; + +class PolyTriVertexShader : public PolyVertexShader +{ +public: + ShadedTriVertex Shade(PolyTriangleThreadData *thread, const PolyDrawArgs &drawargs, const void *vertices, int index) override; +}; + class PolyTriangleThreadData { public: @@ -62,9 +79,13 @@ public: void SetTwoSided(bool value) { twosided = value; } void SetWeaponScene(bool value) { weaponScene = value; } void SetModelVertexShader(int frame1, int frame2, float interpolationFactor) { modelFrame1 = frame1; modelFrame2 = frame2; modelInterpolationFactor = interpolationFactor; } + void SetVertexShader(PolyVertexShader *shader) { vertexShader = shader; } + void SetVertexBuffer(const void *data) { vertices = data; } + void SetIndexBuffer(const void *data) { elements = (const unsigned int *)data; } - void DrawElements(const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode); - void DrawArray(const PolyDrawArgs &args, const void *vertices, int vcount, PolyDrawMode mode); + void PushConstants(const PolyDrawArgs &args); + void DrawIndexed(int index, int count, PolyDrawMode mode); + void Draw(int index, int vcount, PolyDrawMode mode); int32_t core; int32_t num_cores; @@ -113,8 +134,12 @@ public: int viewport_y = 0; + PolyDrawArgs drawargs; + + const void *vertices = nullptr; + const unsigned int *elements = nullptr; + private: - ShadedTriVertex ShadeVertex(const PolyDrawArgs &drawargs, const void *vertices, int index); void DrawShadedTriangle(const ShadedTriVertex *vertices, bool ccw, TriDrawTriangleArgs *args); static bool IsDegenerate(const ShadedTriVertex *vertices); static bool IsFrontfacing(TriDrawTriangleArgs *args); @@ -125,13 +150,18 @@ private: int viewport_height = 0; bool ccw = true; bool twosided = false; +public: const Mat4f *objectToClip = nullptr; const Mat4f *objectToWorld = nullptr; +private: int modelFrame1 = -1; int modelFrame2 = -1; float modelInterpolationFactor = 0.0f; + PolyVertexShader *vertexShader = nullptr; enum { max_additional_vertices = 16 }; + + friend class PolyTriVertexShader; }; class PolyDrawerCommand : public DrawerCommand @@ -139,6 +169,36 @@ class PolyDrawerCommand : public DrawerCommand public: }; +class PolySetVertexBufferCommand : public PolyDrawerCommand +{ +public: + PolySetVertexBufferCommand(const void *vertices); + void Execute(DrawerThread *thread) override; + +private: + const void *vertices; +}; + +class PolySetIndexBufferCommand : public PolyDrawerCommand +{ +public: + PolySetIndexBufferCommand(const void *indices); + void Execute(DrawerThread *thread) override; + +private: + const void *indices; +}; + +class PolySetVertexShaderCommand : public PolyDrawerCommand +{ +public: + PolySetVertexShaderCommand(PolyVertexShader *shader); + void Execute(DrawerThread *thread) override; + +private: + PolyVertexShader *shader; +}; + class PolySetTransformCommand : public PolyDrawerCommand { public: @@ -238,30 +298,39 @@ private: bool dest_bgra; }; -class DrawPolyTrianglesCommand : public PolyDrawerCommand +class PolyPushConstantsCommand : public PolyDrawerCommand { public: - DrawPolyTrianglesCommand(const PolyDrawArgs &args, const void *vertices, const unsigned int *elements, int count, PolyDrawMode mode); + PolyPushConstantsCommand(const PolyDrawArgs &args); void Execute(DrawerThread *thread) override; private: PolyDrawArgs args; - const void *vertices; - const unsigned int *elements; - int count; - PolyDrawMode mode; }; -#if 0 -class DrawRectCommand : public PolyDrawerCommand +class PolyDrawCommand : public PolyDrawerCommand { public: - DrawRectCommand(const RectDrawArgs &args) : args(args) { } + PolyDrawCommand(int index, int count, PolyDrawMode mode); void Execute(DrawerThread *thread) override; private: - RectDrawArgs args; + int index; + int count; + PolyDrawMode mode; +}; + +class PolyDrawIndexedCommand : public PolyDrawerCommand +{ +public: + PolyDrawIndexedCommand(int index, int count, PolyDrawMode mode); + + void Execute(DrawerThread *thread) override; + +private: + int index; + int count; + PolyDrawMode mode; }; -#endif diff --git a/src/rendering/swrenderer/things/r_model.cpp b/src/rendering/swrenderer/things/r_model.cpp index 079b45199..b59170128 100644 --- a/src/rendering/swrenderer/things/r_model.cpp +++ b/src/rendering/swrenderer/things/r_model.cpp @@ -148,6 +148,8 @@ namespace swrenderer SWModelRenderer::SWModelRenderer(RenderThread *thread, Fake3DTranslucent clip3DFloor, Mat4f *worldToClip, bool mirrorWorldToClip) : Thread(thread), Clip3DFloor(clip3DFloor), WorldToClip(worldToClip), MirrorWorldToClip(mirrorWorldToClip) { + static PolyTriVertexShader shader; + PolyTriangleDrawer::SetVertexShader(thread->DrawQueue, &shader); } void SWModelRenderer::AddLights(AActor *actor) @@ -365,7 +367,8 @@ namespace swrenderer args.SetClipPlane(1, ClipTop); args.SetClipPlane(2, ClipBottom); - PolyTriangleDrawer::DrawArray(Thread->DrawQueue, args, VertexBuffer + start, count); + PolyTriangleDrawer::PushConstants(Thread->DrawQueue, args); + PolyTriangleDrawer::Draw(Thread->DrawQueue, start, count); } void SWModelRenderer::DrawElements(int numIndices, size_t offset) @@ -383,7 +386,8 @@ namespace swrenderer args.SetClipPlane(1, ClipTop); args.SetClipPlane(2, ClipBottom); - PolyTriangleDrawer::DrawElements(Thread->DrawQueue, args, VertexBuffer, IndexBuffer + offset / sizeof(unsigned int), numIndices); + PolyTriangleDrawer::PushConstants(Thread->DrawQueue, args); + PolyTriangleDrawer::DrawIndexed(Thread->DrawQueue, static_cast(offset / sizeof(unsigned int)), numIndices); } ///////////////////////////////////////////////////////////////////////////// @@ -419,8 +423,12 @@ namespace swrenderer void SWModelVertexBuffer::SetupFrame(FModelRenderer *renderer, unsigned int frame1, unsigned int frame2, unsigned int size) { SWModelRenderer *swrenderer = (SWModelRenderer *)renderer; - swrenderer->VertexBuffer = mVertexBuffer.Size() ? &mVertexBuffer[0] : nullptr; - swrenderer->IndexBuffer = mIndexBuffer.Size() ? &mIndexBuffer[0] : nullptr; + + if (mVertexBuffer.Size() > 0) + PolyTriangleDrawer::SetVertexBuffer(swrenderer->Thread->DrawQueue, &mVertexBuffer[0]); + if (mIndexBuffer.Size() > 0) + PolyTriangleDrawer::SetIndexBuffer(swrenderer->Thread->DrawQueue, &mIndexBuffer[0]); + PolyTriangleDrawer::SetModelVertexShader(swrenderer->Thread->DrawQueue, frame1, frame2, swrenderer->InterpolationFactor); } } diff --git a/src/rendering/swrenderer/things/r_model.h b/src/rendering/swrenderer/things/r_model.h index 76509123f..b404c03d1 100644 --- a/src/rendering/swrenderer/things/r_model.h +++ b/src/rendering/swrenderer/things/r_model.h @@ -90,8 +90,6 @@ namespace swrenderer Mat4f ObjectToWorld; PolyClipPlane ClipTop, ClipBottom; FTexture *SkinTexture = nullptr; - unsigned int *IndexBuffer = nullptr; - FModelVertex *VertexBuffer = nullptr; float InterpolationFactor = 0.0; Mat4f *WorldToClip = nullptr; bool MirrorWorldToClip = false;