mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-12-01 16:32:17 +00:00
- create a renderer backend based on softpoly's drawers
This commit is contained in:
parent
8a90946094
commit
0eda298db2
21 changed files with 1317 additions and 9 deletions
|
@ -510,7 +510,8 @@ set( PLAT_WIN32_SOURCES
|
||||||
win32/gl_sysfb.cpp
|
win32/gl_sysfb.cpp
|
||||||
win32/base_sysfb.cpp
|
win32/base_sysfb.cpp
|
||||||
win32/win32basevideo.cpp
|
win32/win32basevideo.cpp
|
||||||
win32/win32glvideo.cpp)
|
win32/win32glvideo.cpp
|
||||||
|
win32/win32polyvideo.cpp)
|
||||||
|
|
||||||
if (HAVE_VULKAN)
|
if (HAVE_VULKAN)
|
||||||
set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} win32/win32vulkanvideo.cpp )
|
set (PLAT_WIN32_SOURCES ${PLAT_WIN32_SOURCES} win32/win32vulkanvideo.cpp )
|
||||||
|
@ -713,6 +714,7 @@ file( GLOB HEADER_FILES
|
||||||
rendering/polyrenderer/math/*.h
|
rendering/polyrenderer/math/*.h
|
||||||
rendering/polyrenderer/drawers/*.h
|
rendering/polyrenderer/drawers/*.h
|
||||||
rendering/polyrenderer/scene/*.h
|
rendering/polyrenderer/scene/*.h
|
||||||
|
rendering/polyrenderer/backend/*.h
|
||||||
rendering/hwrenderer/data/*.h
|
rendering/hwrenderer/data/*.h
|
||||||
rendering/hwrenderer/dynlights/*.h
|
rendering/hwrenderer/dynlights/*.h
|
||||||
rendering/hwrenderer/models/*.h
|
rendering/hwrenderer/models/*.h
|
||||||
|
@ -927,6 +929,14 @@ if (HAVE_VULKAN)
|
||||||
set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${VULKAN_SOURCES})
|
set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${VULKAN_SOURCES})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set (POLYBACKEND_SOURCES
|
||||||
|
rendering/polyrenderer/backend/poly_framebuffer.cpp
|
||||||
|
rendering/polyrenderer/backend/poly_buffers.cpp
|
||||||
|
rendering/polyrenderer/backend/poly_hwtexture.cpp
|
||||||
|
rendering/polyrenderer/backend/poly_renderstate.cpp
|
||||||
|
)
|
||||||
|
set (FASTMATH_SOURCES ${FASTMATH_SOURCES} ${POLYBACKEND_SOURCES})
|
||||||
|
|
||||||
set (PCH_SOURCES
|
set (PCH_SOURCES
|
||||||
am_map.cpp
|
am_map.cpp
|
||||||
b_bot.cpp
|
b_bot.cpp
|
||||||
|
@ -1555,6 +1565,7 @@ source_group("Rendering\\Poly Renderer" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOU
|
||||||
source_group("Rendering\\Poly Renderer\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/math/.+")
|
source_group("Rendering\\Poly Renderer\\Math" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/math/.+")
|
||||||
source_group("Rendering\\Poly Renderer\\Drawers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/drawers/.+")
|
source_group("Rendering\\Poly Renderer\\Drawers" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/drawers/.+")
|
||||||
source_group("Rendering\\Poly Renderer\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/scene/.+")
|
source_group("Rendering\\Poly Renderer\\Scene" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/scene/.+")
|
||||||
|
source_group("Rendering\\Poly Renderer\\Backend" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/rendering/polyrenderer/backend/.+")
|
||||||
source_group("Render Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+")
|
source_group("Render Data" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/.+")
|
||||||
source_group("Render Data\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/models/.+")
|
source_group("Render Data\\Models" REGULAR_EXPRESSION "^${CMAKE_CURRENT_SOURCE_DIR}/r_data/models/.+")
|
||||||
source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h)
|
source_group("Render Interface" FILES r_defs.h r_renderer.h r_sky.cpp r_sky.h r_state.h r_utility.cpp r_utility.h)
|
||||||
|
|
|
@ -294,9 +294,11 @@ class FTexture
|
||||||
friend class FMaterial;
|
friend class FMaterial;
|
||||||
friend class OpenGLRenderer::FGLRenderState; // For now this needs access to some fields in ApplyMaterial. This should be rerouted through the Material class
|
friend class OpenGLRenderer::FGLRenderState; // For now this needs access to some fields in ApplyMaterial. This should be rerouted through the Material class
|
||||||
friend class VkRenderState;
|
friend class VkRenderState;
|
||||||
|
friend class PolyRenderState;
|
||||||
friend struct FTexCoordInfo;
|
friend struct FTexCoordInfo;
|
||||||
friend class OpenGLRenderer::FHardwareTexture;
|
friend class OpenGLRenderer::FHardwareTexture;
|
||||||
friend class VkHardwareTexture;
|
friend class VkHardwareTexture;
|
||||||
|
friend class PolyHardwareTexture;
|
||||||
friend class FMultiPatchTexture;
|
friend class FMultiPatchTexture;
|
||||||
friend class FSkyBox;
|
friend class FSkyBox;
|
||||||
friend class FBrightmapTexture;
|
friend class FBrightmapTexture;
|
||||||
|
|
131
src/rendering/polyrenderer/backend/poly_buffers.cpp
Normal file
131
src/rendering/polyrenderer/backend/poly_buffers.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
#include "poly_buffers.h"
|
||||||
|
#include "poly_framebuffer.h"
|
||||||
|
#include "poly_renderstate.h"
|
||||||
|
#include "doomerrors.h"
|
||||||
|
|
||||||
|
PolyBuffer *PolyBuffer::First = nullptr;
|
||||||
|
|
||||||
|
PolyBuffer::PolyBuffer()
|
||||||
|
{
|
||||||
|
Next = First;
|
||||||
|
First = this;
|
||||||
|
if (Next) Next->Prev = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolyBuffer::~PolyBuffer()
|
||||||
|
{
|
||||||
|
if (Next) Next->Prev = Prev;
|
||||||
|
if (Prev) Prev->Next = Next;
|
||||||
|
else First = Next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::ResetAll()
|
||||||
|
{
|
||||||
|
for (PolyBuffer *cur = PolyBuffer::First; cur; cur = cur->Next)
|
||||||
|
cur->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::Reset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::SetData(size_t size, const void *data, bool staticdata)
|
||||||
|
{
|
||||||
|
mData.resize(size);
|
||||||
|
map = mData.data();
|
||||||
|
if (data)
|
||||||
|
memcpy(map, data, size);
|
||||||
|
buffersize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::SetSubData(size_t offset, size_t size, const void *data)
|
||||||
|
{
|
||||||
|
memcpy(static_cast<uint8_t*>(map) + offset, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::Resize(size_t newsize)
|
||||||
|
{
|
||||||
|
mData.resize(newsize);
|
||||||
|
buffersize = newsize;
|
||||||
|
map = mData.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::Map()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::Unmap()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void *PolyBuffer::Lock(unsigned int size)
|
||||||
|
{
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyBuffer::Unlock()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void PolyVertexBuffer::SetFormat(int numBindingPoints, int numAttributes, size_t stride, const FVertexBufferAttribute *attrs)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < numAttributes; j++)
|
||||||
|
{
|
||||||
|
mOffsets[attrs[j].location] = attrs[j].offset;
|
||||||
|
}
|
||||||
|
mStride = stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyVertexBuffer::CopyVertices(TriVertex *dst, int count, int index)
|
||||||
|
{
|
||||||
|
size_t stride = mStride;
|
||||||
|
size_t offsetVertex = mOffsets[VATTR_VERTEX];
|
||||||
|
size_t offsetTexcoord = mOffsets[VATTR_TEXCOORD];
|
||||||
|
uint8_t *vertex = static_cast<uint8_t*>(map) + stride * index;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
dst[i].x = *reinterpret_cast<float*>(vertex + offsetVertex);
|
||||||
|
dst[i].y = *reinterpret_cast<float*>(vertex + offsetVertex + 4);
|
||||||
|
dst[i].z = *reinterpret_cast<float*>(vertex + offsetVertex + 8);
|
||||||
|
dst[i].w = 1.0f;
|
||||||
|
dst[i].v = *reinterpret_cast<float*>(vertex + offsetTexcoord);
|
||||||
|
dst[i].u = *reinterpret_cast<float*>(vertex + offsetTexcoord + 4);
|
||||||
|
vertex += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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<uint8_t*>(map);
|
||||||
|
|
||||||
|
elements += index;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
uint8_t *vertex = vertices + stride * elements[i];
|
||||||
|
dst[i].x = *reinterpret_cast<float*>(vertex + offsetVertex);
|
||||||
|
dst[i].y = *reinterpret_cast<float*>(vertex + offsetVertex + 4);
|
||||||
|
dst[i].z = *reinterpret_cast<float*>(vertex + offsetVertex + 8);
|
||||||
|
dst[i].w = 1.0f;
|
||||||
|
dst[i].v = *reinterpret_cast<float*>(vertex + offsetTexcoord);
|
||||||
|
dst[i].u = *reinterpret_cast<float*>(vertex + offsetTexcoord + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
void PolyDataBuffer::BindRange(size_t start, size_t length)
|
||||||
|
{
|
||||||
|
GetPolyFrameBuffer()->GetRenderState()->Bind(this, (uint32_t)start, (uint32_t)length);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyDataBuffer::BindBase()
|
||||||
|
{
|
||||||
|
GetPolyFrameBuffer()->GetRenderState()->Bind(this, 0, (uint32_t)buffersize);
|
||||||
|
}
|
72
src/rendering/polyrenderer/backend/poly_buffers.h
Normal file
72
src/rendering/polyrenderer/backend/poly_buffers.h
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "hwrenderer/data/buffers.h"
|
||||||
|
#include "utility/tarray.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
// silence bogus warning C4250: 'PolyVertexBuffer': inherits 'PolyBuffer::PolyBuffer::SetData' via dominance
|
||||||
|
// According to internet infos, the warning is erroneously emitted in this case.
|
||||||
|
#pragma warning(disable:4250)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct TriVertex;
|
||||||
|
|
||||||
|
class PolyBuffer : virtual public IBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolyBuffer();
|
||||||
|
~PolyBuffer();
|
||||||
|
|
||||||
|
static void ResetAll();
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
void SetData(size_t size, const void *data, bool staticdata) override;
|
||||||
|
void SetSubData(size_t offset, size_t size, const void *data) override;
|
||||||
|
void Resize(size_t newsize) override;
|
||||||
|
|
||||||
|
void Map() override;
|
||||||
|
void Unmap() override;
|
||||||
|
|
||||||
|
void *Lock(unsigned int size) override;
|
||||||
|
void Unlock() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static PolyBuffer *First;
|
||||||
|
PolyBuffer *Prev = nullptr;
|
||||||
|
PolyBuffer *Next = nullptr;
|
||||||
|
std::vector<uint32_t> mData;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PolyVertexBuffer : public IVertexBuffer, public PolyBuffer
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t mOffsets[VATTR_MAX] = {};
|
||||||
|
size_t mStride = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class PolyIndexBuffer : public IIndexBuffer, public PolyBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolyIndexBuffer() { }
|
||||||
|
};
|
||||||
|
|
||||||
|
class PolyDataBuffer : public IDataBuffer, public PolyBuffer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolyDataBuffer(int bindingpoint, bool ssbo, bool needresize) : bindingpoint(bindingpoint)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void BindRange(size_t start, size_t length) override;
|
||||||
|
void BindBase() override;
|
||||||
|
|
||||||
|
int bindingpoint;
|
||||||
|
};
|
558
src/rendering/polyrenderer/backend/poly_framebuffer.cpp
Normal file
558
src/rendering/polyrenderer/backend/poly_framebuffer.cpp
Normal file
|
@ -0,0 +1,558 @@
|
||||||
|
|
||||||
|
#include "v_video.h"
|
||||||
|
#include "m_png.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "r_videoscale.h"
|
||||||
|
#include "actor.h"
|
||||||
|
#include "i_time.h"
|
||||||
|
#include "g_game.h"
|
||||||
|
#include "gamedata/fonts/v_text.h"
|
||||||
|
|
||||||
|
#include "hwrenderer/utility/hw_clock.h"
|
||||||
|
#include "hwrenderer/utility/hw_vrmodes.h"
|
||||||
|
#include "hwrenderer/utility/hw_cvars.h"
|
||||||
|
#include "hwrenderer/models/hw_models.h"
|
||||||
|
#include "hwrenderer/scene/hw_skydome.h"
|
||||||
|
#include "hwrenderer/scene/hw_fakeflat.h"
|
||||||
|
#include "hwrenderer/scene/hw_drawinfo.h"
|
||||||
|
#include "hwrenderer/scene/hw_portal.h"
|
||||||
|
#include "hwrenderer/data/hw_viewpointbuffer.h"
|
||||||
|
#include "hwrenderer/data/flatvertices.h"
|
||||||
|
#include "hwrenderer/data/shaderuniforms.h"
|
||||||
|
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
||||||
|
#include "hwrenderer/postprocessing/hw_postprocess.h"
|
||||||
|
|
||||||
|
#include "swrenderer/r_swscene.h"
|
||||||
|
|
||||||
|
#include "poly_framebuffer.h"
|
||||||
|
#include "poly_buffers.h"
|
||||||
|
#include "poly_renderstate.h"
|
||||||
|
#include "poly_hwtexture.h"
|
||||||
|
#include "doomerrors.h"
|
||||||
|
|
||||||
|
void Draw2D(F2DDrawer *drawer, FRenderState &state);
|
||||||
|
void DoWriteSavePic(FileWriter *file, ESSType ssformat, uint8_t *scr, int width, int height, sector_t *viewsector, bool upsidedown);
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, r_drawvoxels)
|
||||||
|
EXTERN_CVAR(Int, gl_tonemap)
|
||||||
|
EXTERN_CVAR(Int, screenblocks)
|
||||||
|
EXTERN_CVAR(Bool, cl_capfps)
|
||||||
|
EXTERN_CVAR(Bool, gl_no_skyclear)
|
||||||
|
|
||||||
|
extern bool NoInterpolateView;
|
||||||
|
extern int rendered_commandbuffers;
|
||||||
|
extern int current_rendered_commandbuffers;
|
||||||
|
|
||||||
|
extern bool gpuStatActive;
|
||||||
|
extern bool keepGpuStatActive;
|
||||||
|
extern FString gpuStatOutput;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
void I_PresentPolyImage(int w, int h, const void *pixels);
|
||||||
|
#else
|
||||||
|
void I_PresentPolyImage(int w, int h, const void *pixels) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
PolyFrameBuffer::PolyFrameBuffer(void *hMonitor, bool fullscreen) : Super(hMonitor, fullscreen)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PolyFrameBuffer::~PolyFrameBuffer()
|
||||||
|
{
|
||||||
|
// screen is already null at this point, but PolyHardwareTexture::ResetAll needs it during clean up. Is there a better way we can do this?
|
||||||
|
auto tmp = screen;
|
||||||
|
screen = this;
|
||||||
|
|
||||||
|
PolyHardwareTexture::ResetAll();
|
||||||
|
PolyBuffer::ResetAll();
|
||||||
|
PPResource::ResetAll();
|
||||||
|
|
||||||
|
delete mVertexData;
|
||||||
|
delete mSkyData;
|
||||||
|
delete mViewpoints;
|
||||||
|
delete mLights;
|
||||||
|
mShadowMap.Reset();
|
||||||
|
|
||||||
|
screen = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::InitializeState()
|
||||||
|
{
|
||||||
|
gl_vendorstring = "Poly";
|
||||||
|
hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
|
||||||
|
glslversion = 4.50f;
|
||||||
|
uniformblockalignment = 1;
|
||||||
|
maxuniformblock = 0x7fffffff;
|
||||||
|
|
||||||
|
mVertexData = new FFlatVertexBuffer(GetWidth(), GetHeight());
|
||||||
|
mSkyData = new FSkyVertexBuffer;
|
||||||
|
mViewpoints = new GLViewpointBuffer;
|
||||||
|
mLights = new FLightBuffer();
|
||||||
|
|
||||||
|
mRenderState.reset(new PolyRenderState());
|
||||||
|
|
||||||
|
CheckCanvas();
|
||||||
|
|
||||||
|
PolyTriangleDrawer::SetTransform(GetDrawCommands(), GetFrameMemory()->NewObject<Mat4f>(Mat4f::Identity()), nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::CheckCanvas()
|
||||||
|
{
|
||||||
|
if (!mCanvas || mCanvas->GetWidth() != GetWidth() || mCanvas->GetHeight() != GetHeight())
|
||||||
|
{
|
||||||
|
DrawerThreads::WaitForWorkers();
|
||||||
|
|
||||||
|
mCanvas.reset(new DCanvas(0, 0, true));
|
||||||
|
mCanvas->Resize(GetWidth(), GetHeight(), false);
|
||||||
|
|
||||||
|
PolyTriangleDrawer::SetViewport(GetDrawCommands(), 0, 0, mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DrawerCommandQueuePtr &PolyFrameBuffer::GetDrawCommands()
|
||||||
|
{
|
||||||
|
if (!mDrawCommands)
|
||||||
|
mDrawCommands = std::make_shared<DrawerCommandQueue>(&mFrameMemory);
|
||||||
|
return mDrawCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::FlushDrawCommands()
|
||||||
|
{
|
||||||
|
if (mDrawCommands)
|
||||||
|
{
|
||||||
|
DrawerThreads::Execute(mDrawCommands);
|
||||||
|
mDrawCommands.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::Update()
|
||||||
|
{
|
||||||
|
twoD.Reset();
|
||||||
|
Flush3D.Reset();
|
||||||
|
|
||||||
|
Flush3D.Clock();
|
||||||
|
|
||||||
|
Draw2D();
|
||||||
|
Clear2D();
|
||||||
|
|
||||||
|
Flush3D.Unclock();
|
||||||
|
|
||||||
|
FlushDrawCommands();
|
||||||
|
DrawerThreads::WaitForWorkers();
|
||||||
|
mFrameMemory.Clear();
|
||||||
|
|
||||||
|
if (mCanvas && GetClientWidth() == mCanvas->GetWidth() && GetClientHeight() == mCanvas->GetHeight())
|
||||||
|
{
|
||||||
|
I_PresentPolyImage(mCanvas->GetWidth(), mCanvas->GetHeight(), mCanvas->GetPixels());
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckCanvas();
|
||||||
|
PolyTriangleDrawer::SetTransform(GetDrawCommands(), GetFrameMemory()->NewObject<Mat4f>(Mat4f::Identity()), nullptr);
|
||||||
|
|
||||||
|
Super::Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PolyFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height)
|
||||||
|
{
|
||||||
|
if (!V_IsHardwareRenderer())
|
||||||
|
{
|
||||||
|
Super::WriteSavePic(player, file, width, height);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sector_t *PolyFrameBuffer::RenderView(player_t *player)
|
||||||
|
{
|
||||||
|
// To do: this is virtually identical to FGLRenderer::RenderView and should be merged.
|
||||||
|
|
||||||
|
mRenderState->SetVertexBuffer(screen->mVertexData);
|
||||||
|
screen->mVertexData->Reset();
|
||||||
|
|
||||||
|
sector_t *retsec;
|
||||||
|
if (!V_IsHardwareRenderer())
|
||||||
|
{
|
||||||
|
if (!swdrawer) swdrawer.reset(new SWSceneDrawer);
|
||||||
|
retsec = swdrawer->RenderView(player);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hw_ClearFakeFlat();
|
||||||
|
|
||||||
|
iter_dlightf = iter_dlight = draw_dlight = draw_dlightf = 0;
|
||||||
|
|
||||||
|
checkBenchActive();
|
||||||
|
|
||||||
|
// reset statistics counters
|
||||||
|
ResetProfilingData();
|
||||||
|
|
||||||
|
// Get this before everything else
|
||||||
|
if (cl_capfps || r_NoInterpolate) r_viewpoint.TicFrac = 1.;
|
||||||
|
else r_viewpoint.TicFrac = I_GetTimeFrac();
|
||||||
|
|
||||||
|
screen->mLights->Clear();
|
||||||
|
screen->mViewpoints->Clear();
|
||||||
|
|
||||||
|
// NoInterpolateView should have no bearing on camera textures, but needs to be preserved for the main view below.
|
||||||
|
bool saved_niv = NoInterpolateView;
|
||||||
|
NoInterpolateView = false;
|
||||||
|
|
||||||
|
// Shader start time does not need to be handled per level. Just use the one from the camera to render from.
|
||||||
|
GetRenderState()->CheckTimer(player->camera->Level->ShaderStartTime);
|
||||||
|
// prepare all camera textures that have been used in the last frame.
|
||||||
|
// This must be done for all levels, not just the primary one!
|
||||||
|
for (auto Level : AllLevels())
|
||||||
|
{
|
||||||
|
Level->canvasTextureInfo.UpdateAll([&](AActor *camera, FCanvasTexture *camtex, double fov)
|
||||||
|
{
|
||||||
|
RenderTextureView(camtex, camera, fov);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
NoInterpolateView = saved_niv;
|
||||||
|
|
||||||
|
// now render the main view
|
||||||
|
float fovratio;
|
||||||
|
float ratio = r_viewwindow.WidescreenRatio;
|
||||||
|
if (r_viewwindow.WidescreenRatio >= 1.3f)
|
||||||
|
{
|
||||||
|
fovratio = 1.333333f;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fovratio = ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
retsec = RenderViewpoint(r_viewpoint, player->camera, NULL, r_viewpoint.FieldOfView.Degrees, ratio, fovratio, true, true);
|
||||||
|
}
|
||||||
|
All.Unclock();
|
||||||
|
return retsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
sector_t *PolyFrameBuffer::RenderViewpoint(FRenderViewpoint &mainvp, AActor * camera, IntRect * bounds, float fov, float ratio, float fovratio, bool mainview, bool toscreen)
|
||||||
|
{
|
||||||
|
// To do: this is virtually identical to FGLRenderer::RenderViewpoint and should be merged.
|
||||||
|
|
||||||
|
R_SetupFrame(mainvp, r_viewwindow, camera);
|
||||||
|
|
||||||
|
if (mainview && toscreen)
|
||||||
|
UpdateShadowMap();
|
||||||
|
|
||||||
|
// Update the attenuation flag of all light defaults for each viewpoint.
|
||||||
|
// This function will only do something if the setting differs.
|
||||||
|
FLightDefaults::SetAttenuationForLevel(!!(camera->Level->flags3 & LEVEL3_ATTENUATE));
|
||||||
|
|
||||||
|
// Render (potentially) multiple views for stereo 3d
|
||||||
|
// Fixme. The view offsetting should be done with a static table and not require setup of the entire render state for the mode.
|
||||||
|
auto vrmode = VRMode::GetVRMode(mainview && toscreen);
|
||||||
|
for (int eye_ix = 0; eye_ix < vrmode->mEyeCount; ++eye_ix)
|
||||||
|
{
|
||||||
|
const auto &eye = vrmode->mEyes[eye_ix];
|
||||||
|
screen->SetViewportRects(bounds);
|
||||||
|
|
||||||
|
if (mainview) // Bind the scene frame buffer and turn on draw buffers used by ssao
|
||||||
|
{
|
||||||
|
//mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), Poly_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
||||||
|
bool useSSAO = (gl_ssao != 0);
|
||||||
|
GetRenderState()->SetPassType(useSSAO ? GBUFFER_PASS : NORMAL_PASS);
|
||||||
|
GetRenderState()->EnableDrawBuffers(GetRenderState()->GetPassDrawBufferCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto di = HWDrawInfo::StartDrawInfo(mainvp.ViewLevel, nullptr, mainvp, nullptr);
|
||||||
|
auto &vp = di->Viewpoint;
|
||||||
|
|
||||||
|
di->Set3DViewport(*GetRenderState());
|
||||||
|
di->SetViewArea();
|
||||||
|
auto cm = di->SetFullbrightFlags(mainview ? vp.camera->player : nullptr);
|
||||||
|
di->Viewpoint.FieldOfView = fov; // Set the real FOV for the current scene (it's not necessarily the same as the global setting in r_viewpoint)
|
||||||
|
|
||||||
|
// Stereo mode specific perspective projection
|
||||||
|
di->VPUniforms.mProjectionMatrix = eye.GetProjection(fov, ratio, fovratio);
|
||||||
|
// Stereo mode specific viewpoint adjustment
|
||||||
|
vp.Pos += eye.GetViewShift(vp.HWAngles.Yaw.Degrees);
|
||||||
|
di->SetupView(*GetRenderState(), vp.Pos.X, vp.Pos.Y, vp.Pos.Z, false, false);
|
||||||
|
|
||||||
|
// std::function until this can be done better in a cross-API fashion.
|
||||||
|
di->ProcessScene(toscreen, [&](HWDrawInfo *di, int mode) {
|
||||||
|
DrawScene(di, mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mainview)
|
||||||
|
{
|
||||||
|
PostProcess.Clock();
|
||||||
|
if (toscreen) di->EndDrawScene(mainvp.sector, *GetRenderState()); // do not call this for camera textures.
|
||||||
|
|
||||||
|
if (GetRenderState()->GetPassType() == GBUFFER_PASS) // Turn off ssao draw buffers
|
||||||
|
{
|
||||||
|
GetRenderState()->SetPassType(NORMAL_PASS);
|
||||||
|
GetRenderState()->EnableDrawBuffers(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
//mPostprocess->BlitSceneToPostprocess(); // Copy the resulting scene to the current post process texture
|
||||||
|
|
||||||
|
PostProcessScene(cm, [&]() { di->DrawEndScene2D(mainvp.sector, *GetRenderState()); });
|
||||||
|
|
||||||
|
PostProcess.Unclock();
|
||||||
|
}
|
||||||
|
di->EndDrawInfo();
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
if (vrmode->mEyeCount > 1)
|
||||||
|
mBuffers->BlitToEyeTexture(eye_ix);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainvp.sector;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// This doesn't need to clear the fake flat cache. It can be shared between camera textures and the main view of a scene.
|
||||||
|
FMaterial *mat = FMaterial::ValidateTexture(tex, false);
|
||||||
|
auto BaseLayer = static_cast<PolyHardwareTexture*>(mat->GetLayer(0, 0));
|
||||||
|
|
||||||
|
int width = mat->TextureWidth();
|
||||||
|
int height = mat->TextureHeight();
|
||||||
|
PolyTextureImage *image = BaseLayer->GetImage(tex, 0, 0);
|
||||||
|
PolyTextureImage *depthStencil = BaseLayer->GetDepthStencil(tex);
|
||||||
|
|
||||||
|
mRenderState->EndRenderPass();
|
||||||
|
|
||||||
|
PolyImageTransition barrier0;
|
||||||
|
barrier0.addImage(image, Poly_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, true);
|
||||||
|
barrier0.execute(GetDrawCommands());
|
||||||
|
|
||||||
|
mRenderState->SetRenderTarget(image->View.get(), depthStencil->View.get(), image->Image->width, image->Image->height, Poly_FORMAT_R8G8B8A8_UNORM, Poly_SAMPLE_COUNT_1_BIT);
|
||||||
|
|
||||||
|
IntRect bounds;
|
||||||
|
bounds.left = bounds.top = 0;
|
||||||
|
bounds.width = MIN(mat->GetWidth(), image->Image->width);
|
||||||
|
bounds.height = MIN(mat->GetHeight(), image->Image->height);
|
||||||
|
|
||||||
|
FRenderViewpoint texvp;
|
||||||
|
RenderViewpoint(texvp, Viewpoint, &bounds, FOV, (float)width / height, (float)width / height, false, false);
|
||||||
|
|
||||||
|
mRenderState->EndRenderPass();
|
||||||
|
|
||||||
|
PolyImageTransition barrier1;
|
||||||
|
barrier1.addImage(image, Poly_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, false);
|
||||||
|
barrier1.execute(GetDrawCommands());
|
||||||
|
|
||||||
|
mRenderState->SetRenderTarget(GetBuffers()->SceneColor.View.get(), GetBuffers()->SceneDepthStencil.View.get(), GetBuffers()->GetWidth(), GetBuffers()->GetHeight(), Poly_FORMAT_R16G16B16A16_SFLOAT, GetBuffers()->GetSceneSamples());
|
||||||
|
|
||||||
|
tex->SetUpdated(true);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::DrawScene(HWDrawInfo *di, int drawmode)
|
||||||
|
{
|
||||||
|
// To do: this is virtually identical to FGLRenderer::DrawScene and should be merged.
|
||||||
|
|
||||||
|
static int recursion = 0;
|
||||||
|
static int ssao_portals_available = 0;
|
||||||
|
const auto &vp = di->Viewpoint;
|
||||||
|
|
||||||
|
bool applySSAO = false;
|
||||||
|
if (drawmode == DM_MAINVIEW)
|
||||||
|
{
|
||||||
|
ssao_portals_available = gl_ssao_portals;
|
||||||
|
applySSAO = true;
|
||||||
|
}
|
||||||
|
else if (drawmode == DM_OFFSCREEN)
|
||||||
|
{
|
||||||
|
ssao_portals_available = 0;
|
||||||
|
}
|
||||||
|
else if (drawmode == DM_PORTAL && ssao_portals_available > 0)
|
||||||
|
{
|
||||||
|
applySSAO = true;
|
||||||
|
ssao_portals_available--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vp.camera != nullptr)
|
||||||
|
{
|
||||||
|
ActorRenderFlags savedflags = vp.camera->renderflags;
|
||||||
|
di->CreateScene(drawmode == DM_MAINVIEW);
|
||||||
|
vp.camera->renderflags = savedflags;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
di->CreateScene(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
GetRenderState()->SetDepthMask(true);
|
||||||
|
if (!gl_no_skyclear) screen->mPortalState->RenderFirstSkyPortal(recursion, di, *GetRenderState());
|
||||||
|
|
||||||
|
di->RenderScene(*GetRenderState());
|
||||||
|
|
||||||
|
if (applySSAO && GetRenderState()->GetPassType() == GBUFFER_PASS)
|
||||||
|
{
|
||||||
|
//mPostprocess->AmbientOccludeScene(di->VPUniforms.mProjectionMatrix.get()[5]);
|
||||||
|
//screen->mViewpoints->Bind(*GetRenderState(), di->vpIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle all portals after rendering the opaque objects but before
|
||||||
|
// doing all translucent stuff
|
||||||
|
recursion++;
|
||||||
|
screen->mPortalState->EndFrame(di, *GetRenderState());
|
||||||
|
recursion--;
|
||||||
|
di->RenderTranslucent(*GetRenderState());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D)
|
||||||
|
{
|
||||||
|
afterBloomDrawEndScene2D();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t PolyFrameBuffer::GetCaps()
|
||||||
|
{
|
||||||
|
if (!V_IsHardwareRenderer())
|
||||||
|
return Super::GetCaps();
|
||||||
|
|
||||||
|
// describe our basic feature set
|
||||||
|
ActorRenderFeatureFlags FlagSet = RFF_FLATSPRITES | RFF_MODELS | RFF_SLOPE3DFLOORS |
|
||||||
|
RFF_TILTPITCH | RFF_ROLLSPRITES | RFF_POLYGONAL | RFF_MATSHADER | RFF_POSTSHADER | RFF_BRIGHTMAP;
|
||||||
|
if (r_drawvoxels)
|
||||||
|
FlagSet |= RFF_VOXELS;
|
||||||
|
|
||||||
|
if (gl_tonemap != 5) // not running palette tonemap shader
|
||||||
|
FlagSet |= RFF_TRUECOLOR;
|
||||||
|
|
||||||
|
return (uint32_t)FlagSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::SetVSync(bool vsync)
|
||||||
|
{
|
||||||
|
// This is handled in PolySwapChain::AcquireImage.
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::CleanForRestart()
|
||||||
|
{
|
||||||
|
// force recreation of the SW scene drawer to ensure it gets a new set of resources.
|
||||||
|
swdrawer.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::PrecacheMaterial(FMaterial *mat, int translation)
|
||||||
|
{
|
||||||
|
auto tex = mat->tex;
|
||||||
|
if (tex->isSWCanvas()) return;
|
||||||
|
|
||||||
|
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
|
||||||
|
int flags = mat->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled()) ? CTF_CheckHires : 0;
|
||||||
|
auto base = static_cast<PolyHardwareTexture*>(mat->GetLayer(0, translation));
|
||||||
|
|
||||||
|
base->Precache(mat, translation, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
IHardwareTexture *PolyFrameBuffer::CreateHardwareTexture()
|
||||||
|
{
|
||||||
|
return new PolyHardwareTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
FModelRenderer *PolyFrameBuffer::CreateModelRenderer(int mli)
|
||||||
|
{
|
||||||
|
return new FHWModelRenderer(nullptr, *GetRenderState(), mli);
|
||||||
|
}
|
||||||
|
|
||||||
|
IVertexBuffer *PolyFrameBuffer::CreateVertexBuffer()
|
||||||
|
{
|
||||||
|
return new PolyVertexBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
IIndexBuffer *PolyFrameBuffer::CreateIndexBuffer()
|
||||||
|
{
|
||||||
|
return new PolyIndexBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
IDataBuffer *PolyFrameBuffer::CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize)
|
||||||
|
{
|
||||||
|
return new PolyDataBuffer(bindingpoint, ssbo, needsresize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::SetTextureFilterMode()
|
||||||
|
{
|
||||||
|
TextureFilterChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::TextureFilterChanged()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::StartPrecaching()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::BlurScene(float amount)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::UpdatePalette()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
FTexture *PolyFrameBuffer::WipeStartScreen()
|
||||||
|
{
|
||||||
|
const auto &viewport = screen->mScreenViewport;
|
||||||
|
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
|
||||||
|
auto systex = static_cast<PolyHardwareTexture*>(tex->GetSystemTexture());
|
||||||
|
|
||||||
|
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeStartScreen");
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
FTexture *PolyFrameBuffer::WipeEndScreen()
|
||||||
|
{
|
||||||
|
Draw2D();
|
||||||
|
Clear2D();
|
||||||
|
|
||||||
|
const auto &viewport = screen->mScreenViewport;
|
||||||
|
auto tex = new FWrapperTexture(viewport.width, viewport.height, 1);
|
||||||
|
auto systex = static_cast<PolyHardwareTexture*>(tex->GetSystemTexture());
|
||||||
|
|
||||||
|
systex->CreateWipeTexture(viewport.width, viewport.height, "WipeEndScreen");
|
||||||
|
|
||||||
|
return tex;
|
||||||
|
}
|
||||||
|
|
||||||
|
TArray<uint8_t> PolyFrameBuffer::GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma)
|
||||||
|
{
|
||||||
|
int w = SCREENWIDTH;
|
||||||
|
int h = SCREENHEIGHT;
|
||||||
|
|
||||||
|
IntRect box;
|
||||||
|
box.left = 0;
|
||||||
|
box.top = 0;
|
||||||
|
box.width = w;
|
||||||
|
box.height = h;
|
||||||
|
//mPostprocess->DrawPresentTexture(box, true, true);
|
||||||
|
|
||||||
|
TArray<uint8_t> ScreenshotBuffer(w * h * 3, true);
|
||||||
|
//CopyScreenToBuffer(w, h, ScreenshotBuffer.Data());
|
||||||
|
|
||||||
|
pitch = w * 3;
|
||||||
|
color_type = SS_RGB;
|
||||||
|
gamma = 1.0f;
|
||||||
|
return ScreenshotBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::BeginFrame()
|
||||||
|
{
|
||||||
|
SetViewportRects(nullptr);
|
||||||
|
CheckCanvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::Draw2D()
|
||||||
|
{
|
||||||
|
::Draw2D(&m2DDrawer, *mRenderState);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int PolyFrameBuffer::GetLightBufferBlockSize() const
|
||||||
|
{
|
||||||
|
return mLights->GetBlockSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyFrameBuffer::UpdateShadowMap()
|
||||||
|
{
|
||||||
|
}
|
75
src/rendering/polyrenderer/backend/poly_framebuffer.h
Normal file
75
src/rendering/polyrenderer/backend/poly_framebuffer.h
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "gl_sysfb.h"
|
||||||
|
#include "rendering/swrenderer/r_memory.h"
|
||||||
|
#include "rendering/swrenderer/drawers/r_thread.h"
|
||||||
|
#include "rendering/polyrenderer/drawers/poly_triangle.h"
|
||||||
|
|
||||||
|
struct FRenderViewpoint;
|
||||||
|
class PolyDataBuffer;
|
||||||
|
class PolyRenderState;
|
||||||
|
class SWSceneDrawer;
|
||||||
|
|
||||||
|
class PolyFrameBuffer : public SystemBaseFrameBuffer
|
||||||
|
{
|
||||||
|
typedef SystemBaseFrameBuffer Super;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RenderMemory *GetFrameMemory() { return &mFrameMemory; }
|
||||||
|
PolyRenderState *GetRenderState() { return mRenderState.get(); }
|
||||||
|
const DrawerCommandQueuePtr &GetDrawCommands();
|
||||||
|
void FlushDrawCommands();
|
||||||
|
|
||||||
|
unsigned int GetLightBufferBlockSize() const;
|
||||||
|
|
||||||
|
std::unique_ptr<SWSceneDrawer> swdrawer;
|
||||||
|
|
||||||
|
PolyFrameBuffer(void *hMonitor, bool fullscreen);
|
||||||
|
~PolyFrameBuffer();
|
||||||
|
|
||||||
|
void Update();
|
||||||
|
|
||||||
|
void InitializeState() override;
|
||||||
|
|
||||||
|
void CleanForRestart() override;
|
||||||
|
void PrecacheMaterial(FMaterial *mat, int translation) override;
|
||||||
|
void UpdatePalette() override;
|
||||||
|
uint32_t GetCaps() override;
|
||||||
|
void WriteSavePic(player_t *player, FileWriter *file, int width, int height) override;
|
||||||
|
sector_t *RenderView(player_t *player) override;
|
||||||
|
void SetTextureFilterMode() override;
|
||||||
|
void TextureFilterChanged() override;
|
||||||
|
void StartPrecaching() override;
|
||||||
|
void BeginFrame() override;
|
||||||
|
void BlurScene(float amount) override;
|
||||||
|
void PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D) override;
|
||||||
|
|
||||||
|
IHardwareTexture *CreateHardwareTexture() override;
|
||||||
|
FModelRenderer *CreateModelRenderer(int mli) override;
|
||||||
|
IVertexBuffer *CreateVertexBuffer() override;
|
||||||
|
IIndexBuffer *CreateIndexBuffer() override;
|
||||||
|
IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) override;
|
||||||
|
|
||||||
|
FTexture *WipeStartScreen() override;
|
||||||
|
FTexture *WipeEndScreen() override;
|
||||||
|
|
||||||
|
TArray<uint8_t> GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) override;
|
||||||
|
|
||||||
|
void SetVSync(bool vsync) override;
|
||||||
|
void Draw2D() override;
|
||||||
|
|
||||||
|
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);
|
||||||
|
void DrawScene(HWDrawInfo *di, int drawmode);
|
||||||
|
void UpdateShadowMap();
|
||||||
|
|
||||||
|
void CheckCanvas();
|
||||||
|
|
||||||
|
std::unique_ptr<PolyRenderState> mRenderState;
|
||||||
|
std::unique_ptr<DCanvas> mCanvas;
|
||||||
|
std::shared_ptr<DrawerCommandQueue> mDrawCommands;
|
||||||
|
RenderMemory mFrameMemory;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline PolyFrameBuffer *GetPolyFrameBuffer() { return static_cast<PolyFrameBuffer*>(screen); }
|
131
src/rendering/polyrenderer/backend/poly_hwtexture.cpp
Normal file
131
src/rendering/polyrenderer/backend/poly_hwtexture.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
|
||||||
|
#include "templates.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
|
#include "r_data/colormaps.h"
|
||||||
|
#include "hwrenderer/textures/hw_material.h"
|
||||||
|
#include "hwrenderer/utility/hw_cvars.h"
|
||||||
|
#include "hwrenderer/scene/hw_renderstate.h"
|
||||||
|
#include "poly_framebuffer.h"
|
||||||
|
#include "poly_hwtexture.h"
|
||||||
|
|
||||||
|
PolyHardwareTexture *PolyHardwareTexture::First = nullptr;
|
||||||
|
|
||||||
|
PolyHardwareTexture::PolyHardwareTexture()
|
||||||
|
{
|
||||||
|
Next = First;
|
||||||
|
First = this;
|
||||||
|
if (Next) Next->Prev = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolyHardwareTexture::~PolyHardwareTexture()
|
||||||
|
{
|
||||||
|
if (Next) Next->Prev = Prev;
|
||||||
|
if (Prev) Prev->Next = Next;
|
||||||
|
else First = Next;
|
||||||
|
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyHardwareTexture::ResetAll()
|
||||||
|
{
|
||||||
|
for (PolyHardwareTexture *cur = PolyHardwareTexture::First; cur; cur = cur->Next)
|
||||||
|
cur->Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyHardwareTexture::Reset()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyHardwareTexture::Precache(FMaterial *mat, int translation, int flags)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
int numLayers = mat->GetLayers();
|
||||||
|
GetImage(mat->tex, translation, flags);
|
||||||
|
for (int i = 1; i < numLayers; i++)
|
||||||
|
{
|
||||||
|
FTexture *layer;
|
||||||
|
auto systex = static_cast<PolyHardwareTexture*>(mat->GetLayer(i, 0, &layer));
|
||||||
|
systex->GetImage(layer, 0, mat->isExpanded() ? CTF_Expand : 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
DCanvas *PolyHardwareTexture::GetImage(const FMaterialState &state)
|
||||||
|
{
|
||||||
|
if (!mCanvas)
|
||||||
|
{
|
||||||
|
FMaterial *mat = state.mMaterial;
|
||||||
|
FTexture *tex = state.mMaterial->tex;
|
||||||
|
int clampmode = state.mClampMode;
|
||||||
|
int translation = state.mTranslation;
|
||||||
|
|
||||||
|
if (tex->UseType == ETextureType::SWCanvas) clampmode = CLAMP_NOFILTER;
|
||||||
|
if (tex->isHardwareCanvas()) clampmode = CLAMP_CAMTEX;
|
||||||
|
else if ((tex->isWarped() || tex->shaderindex >= FIRST_USER_SHADER) && clampmode <= CLAMP_XY) clampmode = CLAMP_NONE;
|
||||||
|
|
||||||
|
// Textures that are already scaled in the texture lump will not get replaced by hires textures.
|
||||||
|
int flags = state.mMaterial->isExpanded() ? CTF_Expand : (gl_texture_usehires && !tex->isScaled() && clampmode <= CLAMP_XY) ? CTF_CheckHires : 0;
|
||||||
|
|
||||||
|
if (tex->isHardwareCanvas()) static_cast<FCanvasTexture*>(tex)->NeedUpdate();
|
||||||
|
|
||||||
|
CreateImage(tex, translation, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mCanvas.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyHardwareTexture::AllocateBuffer(int w, int h, int texelsize)
|
||||||
|
{
|
||||||
|
if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h)
|
||||||
|
{
|
||||||
|
mCanvas.reset(new DCanvas(0, 0, texelsize == 4));
|
||||||
|
mCanvas->Resize(w, h, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *PolyHardwareTexture::MapBuffer()
|
||||||
|
{
|
||||||
|
return mCanvas->GetPixels();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int PolyHardwareTexture::CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyHardwareTexture::CreateWipeTexture(int w, int h, const char *name)
|
||||||
|
{
|
||||||
|
if (!mCanvas || mCanvas->GetWidth() != w || mCanvas->GetHeight() != h)
|
||||||
|
{
|
||||||
|
mCanvas.reset(new DCanvas(0, 0, true));
|
||||||
|
mCanvas->Resize(w, h, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyHardwareTexture::CreateImage(FTexture *tex, int translation, int flags)
|
||||||
|
{
|
||||||
|
mCanvas.reset(new DCanvas(0, 0, true));
|
||||||
|
|
||||||
|
if (!tex->isHardwareCanvas())
|
||||||
|
{
|
||||||
|
if (translation <= 0)
|
||||||
|
{
|
||||||
|
translation = -translation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto remap = TranslationToTable(translation);
|
||||||
|
translation = remap == nullptr ? 0 : remap->GetUniqueIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
FTextureBuffer texbuffer = tex->CreateTexBuffer(translation, flags | CTF_ProcessData);
|
||||||
|
mCanvas->Resize(texbuffer.mWidth, texbuffer.mHeight, false);
|
||||||
|
memcpy(mCanvas->GetPixels(), texbuffer.mBuffer, texbuffer.mWidth * texbuffer.mHeight * 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int w = tex->GetWidth();
|
||||||
|
int h = tex->GetHeight();
|
||||||
|
mCanvas->Resize(w, h, false);
|
||||||
|
}
|
||||||
|
}
|
45
src/rendering/polyrenderer/backend/poly_hwtexture.h
Normal file
45
src/rendering/polyrenderer/backend/poly_hwtexture.h
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef LoadImage
|
||||||
|
#undef LoadImage
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SHADED_TEXTURE -1
|
||||||
|
#define DIRECT_PALETTE -2
|
||||||
|
|
||||||
|
#include "tarray.h"
|
||||||
|
#include "hwrenderer/textures/hw_ihwtexture.h"
|
||||||
|
#include "volk/volk.h"
|
||||||
|
|
||||||
|
struct FMaterialState;
|
||||||
|
class PolyBuffer;
|
||||||
|
|
||||||
|
class PolyHardwareTexture : public IHardwareTexture
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolyHardwareTexture();
|
||||||
|
~PolyHardwareTexture();
|
||||||
|
|
||||||
|
static void ResetAll();
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
void Precache(FMaterial *mat, int translation, int flags);
|
||||||
|
|
||||||
|
DCanvas *GetImage(const FMaterialState &state);
|
||||||
|
|
||||||
|
// Software renderer stuff
|
||||||
|
void AllocateBuffer(int w, int h, int texelsize) override;
|
||||||
|
uint8_t *MapBuffer() override;
|
||||||
|
unsigned int CreateTexture(unsigned char * buffer, int w, int h, int texunit, bool mipmap, int translation, const char *name) override;
|
||||||
|
|
||||||
|
// Wipe screen
|
||||||
|
void CreateWipeTexture(int w, int h, const char *name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void CreateImage(FTexture *tex, int translation, int flags);
|
||||||
|
|
||||||
|
static PolyHardwareTexture *First;
|
||||||
|
PolyHardwareTexture *Prev = nullptr;
|
||||||
|
PolyHardwareTexture *Next = nullptr;
|
||||||
|
std::unique_ptr<DCanvas> mCanvas;
|
||||||
|
};
|
178
src/rendering/polyrenderer/backend/poly_renderstate.cpp
Normal file
178
src/rendering/polyrenderer/backend/poly_renderstate.cpp
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
|
||||||
|
#include "polyrenderer/backend/poly_renderstate.h"
|
||||||
|
#include "polyrenderer/backend/poly_framebuffer.h"
|
||||||
|
#include "polyrenderer/backend/poly_hwtexture.h"
|
||||||
|
#include "templates.h"
|
||||||
|
#include "doomstat.h"
|
||||||
|
#include "r_data/colormaps.h"
|
||||||
|
#include "hwrenderer/scene/hw_skydome.h"
|
||||||
|
#include "hwrenderer/scene/hw_viewpointuniforms.h"
|
||||||
|
#include "hwrenderer/dynlights/hw_lightbuffer.h"
|
||||||
|
#include "hwrenderer/utility/hw_cvars.h"
|
||||||
|
#include "hwrenderer/utility/hw_clock.h"
|
||||||
|
#include "hwrenderer/data/flatvertices.h"
|
||||||
|
#include "hwrenderer/data/hw_viewpointbuffer.h"
|
||||||
|
#include "hwrenderer/data/shaderuniforms.h"
|
||||||
|
|
||||||
|
static PolyDrawMode dtToDrawMode[] =
|
||||||
|
{
|
||||||
|
PolyDrawMode::Triangles, // DT_Points
|
||||||
|
PolyDrawMode::Triangles, // DT_Lines
|
||||||
|
PolyDrawMode::Triangles, // DT_Triangles
|
||||||
|
PolyDrawMode::TriangleFan, // DT_TriangleFan
|
||||||
|
PolyDrawMode::TriangleStrip, // DT_TriangleStrip
|
||||||
|
};
|
||||||
|
|
||||||
|
PolyRenderState::PolyRenderState()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::ClearScreen()
|
||||||
|
{
|
||||||
|
screen->mViewpoints->Set2D(*this, SCREENWIDTH, SCREENHEIGHT);
|
||||||
|
SetColor(0, 0, 0);
|
||||||
|
Draw(DT_TriangleStrip, FFlatVertexBuffer::FULLSCREEN_INDEX, 4, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::Draw(int dt, int index, int count, bool apply)
|
||||||
|
{
|
||||||
|
if (apply)
|
||||||
|
Apply();
|
||||||
|
|
||||||
|
auto fb = GetPolyFrameBuffer();
|
||||||
|
TriVertex *vertices = fb->GetFrameMemory()->AllocMemory<TriVertex>(count);
|
||||||
|
static_cast<PolyVertexBuffer*>(mVertexBuffer)->CopyVertices(vertices, count, index);
|
||||||
|
PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::DrawIndexed(int dt, int index, int count, bool apply)
|
||||||
|
{
|
||||||
|
if (apply)
|
||||||
|
Apply();
|
||||||
|
|
||||||
|
auto fb = GetPolyFrameBuffer();
|
||||||
|
TriVertex *vertices = fb->GetFrameMemory()->AllocMemory<TriVertex>(count);
|
||||||
|
static_cast<PolyVertexBuffer*>(mVertexBuffer)->CopyIndexed(vertices, (uint32_t *)mIndexBuffer->Memory(), count, index);
|
||||||
|
PolyTriangleDrawer::DrawArray(fb->GetDrawCommands(), args, vertices, count, dtToDrawMode[dt]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PolyRenderState::SetDepthClamp(bool on)
|
||||||
|
{
|
||||||
|
bool lastValue = mDepthClamp;
|
||||||
|
mDepthClamp = on;
|
||||||
|
return lastValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetDepthMask(bool on)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetDepthFunc(int func)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetDepthRange(float min, float max)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetColorMask(bool r, bool g, bool b, bool a)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetStencil(int offs, int op, int flags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetCulling(int mode)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::EnableClipDistance(int num, bool state)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::Clear(int targets)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::EnableStencil(bool on)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetScissor(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::SetViewport(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::EnableDepthTest(bool on)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::EnableMultisampling(bool on)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::EnableLineSmooth(bool on)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::EnableDrawBuffers(int count)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::Apply()
|
||||||
|
{
|
||||||
|
drawcalls.Clock();
|
||||||
|
|
||||||
|
args.SetStencilTest(false);
|
||||||
|
args.SetDepthTest(false);
|
||||||
|
args.SetWriteStencil(false);
|
||||||
|
args.SetWriteDepth(false);
|
||||||
|
args.SetNoColormap();
|
||||||
|
|
||||||
|
args.SetColor(MAKEARGB(
|
||||||
|
static_cast<uint32_t>(mStreamData.uVertexColor.W * 255.0f + 0.5f),
|
||||||
|
static_cast<uint32_t>(mStreamData.uVertexColor.X * 255.0f + 0.5f),
|
||||||
|
static_cast<uint32_t>(mStreamData.uVertexColor.Y * 255.0f + 0.5f),
|
||||||
|
static_cast<uint32_t>(mStreamData.uVertexColor.Z * 255.0f + 0.5f)), 0);
|
||||||
|
|
||||||
|
if (mMaterial.mChanged && mMaterial.mMaterial)
|
||||||
|
{
|
||||||
|
auto base = static_cast<PolyHardwareTexture*>(mMaterial.mMaterial->GetLayer(0, mMaterial.mTranslation));
|
||||||
|
if (base)
|
||||||
|
{
|
||||||
|
DCanvas *texcanvas = base->GetImage(mMaterial);
|
||||||
|
args.SetTexture(texcanvas->GetPixels(), texcanvas->GetHeight(), texcanvas->GetWidth());
|
||||||
|
args.SetStyle(TriBlendMode::Opaque);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
args.SetStyle(TriBlendMode::Fill);
|
||||||
|
}
|
||||||
|
|
||||||
|
mMaterial.mChanged = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fb = GetPolyFrameBuffer();
|
||||||
|
PolyTriangleDrawer::SetTwoSided(fb->GetDrawCommands(), true);
|
||||||
|
|
||||||
|
drawcalls.Unclock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PolyRenderState::Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length)
|
||||||
|
{
|
||||||
|
if (buffer->bindingpoint == VIEWPOINT_BINDINGPOINT)
|
||||||
|
{
|
||||||
|
HWViewpointUniforms *uniforms = reinterpret_cast<HWViewpointUniforms*>(static_cast<uint8_t*>(buffer->Memory()) + offset);
|
||||||
|
|
||||||
|
Mat4f viewToProj = Mat4f::FromValues(uniforms->mProjectionMatrix.get());
|
||||||
|
Mat4f worldToView = Mat4f::FromValues(uniforms->mViewMatrix.get());
|
||||||
|
|
||||||
|
auto fb = GetPolyFrameBuffer();
|
||||||
|
PolyTriangleDrawer::SetTransform(fb->GetDrawCommands(), fb->GetFrameMemory()->NewObject<Mat4f>(viewToProj * worldToView), nullptr);
|
||||||
|
}
|
||||||
|
}
|
50
src/rendering/polyrenderer/backend/poly_renderstate.h
Normal file
50
src/rendering/polyrenderer/backend/poly_renderstate.h
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "polyrenderer/backend/poly_buffers.h"
|
||||||
|
#include "rendering/polyrenderer/drawers/poly_triangle.h"
|
||||||
|
|
||||||
|
#include "name.h"
|
||||||
|
|
||||||
|
#include "hwrenderer/scene/hw_drawstructs.h"
|
||||||
|
#include "hwrenderer/scene/hw_renderstate.h"
|
||||||
|
#include "hwrenderer/textures/hw_material.h"
|
||||||
|
|
||||||
|
class PolyRenderPassSetup;
|
||||||
|
|
||||||
|
class PolyRenderState : public FRenderState
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PolyRenderState();
|
||||||
|
|
||||||
|
// Draw commands
|
||||||
|
void ClearScreen() override;
|
||||||
|
void Draw(int dt, int index, int count, bool apply = true) override;
|
||||||
|
void DrawIndexed(int dt, int index, int count, bool apply = true) override;
|
||||||
|
|
||||||
|
// Immediate render state change commands. These only change infrequently and should not clutter the render state.
|
||||||
|
bool SetDepthClamp(bool on) override;
|
||||||
|
void SetDepthMask(bool on) override;
|
||||||
|
void SetDepthFunc(int func) override;
|
||||||
|
void SetDepthRange(float min, float max) override;
|
||||||
|
void SetColorMask(bool r, bool g, bool b, bool a) override;
|
||||||
|
void SetStencil(int offs, int op, int flags = -1) override;
|
||||||
|
void SetCulling(int mode) override;
|
||||||
|
void EnableClipDistance(int num, bool state) override;
|
||||||
|
void Clear(int targets) override;
|
||||||
|
void EnableStencil(bool on) override;
|
||||||
|
void SetScissor(int x, int y, int w, int h) override;
|
||||||
|
void SetViewport(int x, int y, int w, int h) override;
|
||||||
|
void EnableDepthTest(bool on) override;
|
||||||
|
void EnableMultisampling(bool on) override;
|
||||||
|
void EnableLineSmooth(bool on) override;
|
||||||
|
void EnableDrawBuffers(int count) override;
|
||||||
|
|
||||||
|
void Bind(PolyDataBuffer *buffer, uint32_t offset, uint32_t length);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Apply();
|
||||||
|
|
||||||
|
bool mDepthClamp = true;
|
||||||
|
PolyDrawArgs args;
|
||||||
|
};
|
|
@ -70,7 +70,9 @@ public:
|
||||||
void SetTexture(FSoftwareTexture *texture, FRenderStyle style);
|
void SetTexture(FSoftwareTexture *texture, FRenderStyle style);
|
||||||
void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style);
|
void SetTexture(FSoftwareTexture *texture, uint32_t translationID, FRenderStyle style);
|
||||||
void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed);
|
void SetLight(FSWColormap *basecolormap, uint32_t lightlevel, double globVis, bool fixed);
|
||||||
|
void SetNoColormap() { mLight = 255; mFixedLight = true; mLightRed = 256; mLightGreen = 256; mLightBlue = 256; mLightAlpha = 256; mFadeRed = 0; mFadeGreen = 0; mFadeBlue = 0; mFadeAlpha = 0; mDesaturate = 0; mSimpleShade = true; mColormaps = nullptr; }
|
||||||
void SetDepthTest(bool enable) { mDepthTest = enable; }
|
void SetDepthTest(bool enable) { mDepthTest = enable; }
|
||||||
|
void SetStencilTest(bool enable) { mStencilTest = enable; }
|
||||||
void SetStencilTestValue(uint8_t stencilTestValue) { mStencilTestValue = stencilTestValue; }
|
void SetStencilTestValue(uint8_t stencilTestValue) { mStencilTestValue = stencilTestValue; }
|
||||||
void SetWriteColor(bool enable) { mWriteColor = enable; }
|
void SetWriteColor(bool enable) { mWriteColor = enable; }
|
||||||
void SetWriteStencil(bool enable, uint8_t stencilWriteValue = 0) { mWriteStencil = enable; mStencilWriteValue = stencilWriteValue; }
|
void SetWriteStencil(bool enable, uint8_t stencilWriteValue = 0) { mWriteStencil = enable; mStencilWriteValue = stencilWriteValue; }
|
||||||
|
@ -92,6 +94,7 @@ public:
|
||||||
const uint8_t *Translation() const { return mTranslation; }
|
const uint8_t *Translation() const { return mTranslation; }
|
||||||
|
|
||||||
bool WriteStencil() const { return mWriteStencil; }
|
bool WriteStencil() const { return mWriteStencil; }
|
||||||
|
bool StencilTest() const { return mStencilTest; }
|
||||||
uint8_t StencilTestValue() const { return mStencilTestValue; }
|
uint8_t StencilTestValue() const { return mStencilTestValue; }
|
||||||
uint8_t StencilWriteValue() const { return mStencilWriteValue; }
|
uint8_t StencilWriteValue() const { return mStencilWriteValue; }
|
||||||
|
|
||||||
|
@ -128,6 +131,7 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool mDepthTest = false;
|
bool mDepthTest = false;
|
||||||
|
bool mStencilTest = true;
|
||||||
bool mWriteStencil = true;
|
bool mWriteStencil = true;
|
||||||
bool mWriteColor = true;
|
bool mWriteColor = true;
|
||||||
bool mWriteDepth = true;
|
bool mWriteDepth = true;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "polyrenderer/drawers/poly_buffer.h"
|
#include "polyrenderer/drawers/poly_buffer.h"
|
||||||
#include "polyrenderer/drawers/poly_draw_args.h"
|
#include "polyrenderer/drawers/poly_draw_args.h"
|
||||||
|
|
||||||
|
class DCanvas;
|
||||||
class PolyDrawerCommand;
|
class PolyDrawerCommand;
|
||||||
|
|
||||||
class PolyTriangleDrawer
|
class PolyTriangleDrawer
|
||||||
|
|
|
@ -143,7 +143,7 @@ void ScreenTriangle::Draw(const TriDrawTriangleArgs *args, PolyTriangleThreadDat
|
||||||
|
|
||||||
int opt = 0;
|
int opt = 0;
|
||||||
if (args->uniforms->DepthTest()) opt |= SWTRI_DepthTest;
|
if (args->uniforms->DepthTest()) opt |= SWTRI_DepthTest;
|
||||||
/*if (args->uniforms->StencilTest())*/ opt |= SWTRI_StencilTest;
|
if (args->uniforms->StencilTest()) opt |= SWTRI_StencilTest;
|
||||||
if (args->uniforms->WriteColor()) opt |= SWTRI_WriteColor;
|
if (args->uniforms->WriteColor()) opt |= SWTRI_WriteColor;
|
||||||
if (args->uniforms->WriteDepth()) opt |= SWTRI_WriteDepth;
|
if (args->uniforms->WriteDepth()) opt |= SWTRI_WriteDepth;
|
||||||
if (args->uniforms->WriteStencil()) opt |= SWTRI_WriteStencil;
|
if (args->uniforms->WriteStencil()) opt |= SWTRI_WriteStencil;
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include "r_data/renderstyle.h"
|
||||||
|
|
||||||
class FString;
|
class FString;
|
||||||
class PolyDrawArgs;
|
class PolyDrawArgs;
|
||||||
|
|
|
@ -42,7 +42,7 @@ Mat4f Mat4f::Identity()
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat4f Mat4f::FromValues(float *matrix)
|
Mat4f Mat4f::FromValues(const float *matrix)
|
||||||
{
|
{
|
||||||
Mat4f m;
|
Mat4f m;
|
||||||
memcpy(m.Matrix, matrix, sizeof(m.Matrix));
|
memcpy(m.Matrix, matrix, sizeof(m.Matrix));
|
||||||
|
|
|
@ -115,7 +115,7 @@ class Mat4f
|
||||||
public:
|
public:
|
||||||
static Mat4f Null();
|
static Mat4f Null();
|
||||||
static Mat4f Identity();
|
static Mat4f Identity();
|
||||||
static Mat4f FromValues(float *matrix);
|
static Mat4f FromValues(const float *matrix);
|
||||||
static Mat4f Transpose(const Mat4f &matrix);
|
static Mat4f Transpose(const Mat4f &matrix);
|
||||||
static Mat4f Translate(float x, float y, float z);
|
static Mat4f Translate(float x, float y, float z);
|
||||||
static Mat4f Scale(float x, float y, float z);
|
static Mat4f Scale(float x, float y, float z);
|
||||||
|
|
|
@ -210,7 +210,7 @@ DCanvas::~DCanvas ()
|
||||||
//
|
//
|
||||||
//==========================================================================
|
//==========================================================================
|
||||||
|
|
||||||
void DCanvas::Resize(int width, int height)
|
void DCanvas::Resize(int width, int height, bool optimizepitch)
|
||||||
{
|
{
|
||||||
Width = width;
|
Width = width;
|
||||||
Height = height;
|
Height = height;
|
||||||
|
@ -221,7 +221,7 @@ void DCanvas::Resize(int width, int height)
|
||||||
// longer than the width. The values used here are all based on
|
// longer than the width. The values used here are all based on
|
||||||
// empirical evidence.
|
// empirical evidence.
|
||||||
|
|
||||||
if (width <= 640)
|
if (width <= 640 || !optimizepitch)
|
||||||
{
|
{
|
||||||
// For low resolutions, just keep the pitch the same as the width.
|
// For low resolutions, just keep the pitch the same as the width.
|
||||||
// Some speedup can be seen using the technique below, but the speedup
|
// Some speedup can be seen using the technique below, but the speedup
|
||||||
|
|
|
@ -326,7 +326,7 @@ class DCanvas
|
||||||
public:
|
public:
|
||||||
DCanvas (int width, int height, bool bgra);
|
DCanvas (int width, int height, bool bgra);
|
||||||
~DCanvas ();
|
~DCanvas ();
|
||||||
void Resize(int width, int height);
|
void Resize(int width, int height, bool optimizepitch = true);
|
||||||
|
|
||||||
// Member variable access
|
// Member variable access
|
||||||
inline uint8_t *GetPixels () const { return Pixels.Data(); }
|
inline uint8_t *GetPixels () const { return Pixels.Data(); }
|
||||||
|
|
|
@ -44,6 +44,7 @@
|
||||||
#include "m_argv.h"
|
#include "m_argv.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "win32glvideo.h"
|
#include "win32glvideo.h"
|
||||||
|
#include "win32polyvideo.h"
|
||||||
#ifdef HAVE_VULKAN
|
#ifdef HAVE_VULKAN
|
||||||
#include "win32vulkanvideo.h"
|
#include "win32vulkanvideo.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -129,8 +130,12 @@ void I_InitGraphics ()
|
||||||
// are the active app. Huh?
|
// are the active app. Huh?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vid_enablevulkan == 2)
|
||||||
|
{
|
||||||
|
Video = new Win32PolyVideo();
|
||||||
|
}
|
||||||
#ifdef HAVE_VULKAN
|
#ifdef HAVE_VULKAN
|
||||||
if (vid_enablevulkan == 1)
|
else if (vid_enablevulkan == 1)
|
||||||
{
|
{
|
||||||
// first try Vulkan, if that fails OpenGL
|
// first try Vulkan, if that fails OpenGL
|
||||||
try
|
try
|
||||||
|
@ -143,8 +148,8 @@ void I_InitGraphics ()
|
||||||
Video = new Win32GLVideo();
|
Video = new Win32GLVideo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
|
else
|
||||||
{
|
{
|
||||||
Video = new Win32GLVideo();
|
Video = new Win32GLVideo();
|
||||||
}
|
}
|
||||||
|
|
23
src/win32/win32polyvideo.cpp
Normal file
23
src/win32/win32polyvideo.cpp
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
#include "hardware.h"
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
extern HWND Window;
|
||||||
|
|
||||||
|
void I_PresentPolyImage(int w, int h, const void *pixels)
|
||||||
|
{
|
||||||
|
BITMAPV5HEADER info = {};
|
||||||
|
info.bV5Size = sizeof(BITMAPV5HEADER);
|
||||||
|
info.bV5Width = w;
|
||||||
|
info.bV5Height = -h;
|
||||||
|
info.bV5Planes = 1;
|
||||||
|
info.bV5BitCount = 32;
|
||||||
|
info.bV5Compression = BI_RGB;
|
||||||
|
info.bV5SizeImage = 0;
|
||||||
|
info.bV5CSType = LCS_WINDOWS_COLOR_SPACE;
|
||||||
|
|
||||||
|
HDC dc = GetDC(Window);
|
||||||
|
SetDIBitsToDevice(dc, 0, 0, w, h, 0, 0, 0, h, pixels, (const BITMAPINFO *)&info, DIB_RGB_COLORS);
|
||||||
|
ReleaseDC(Window, dc);
|
||||||
|
}
|
21
src/win32/win32polyvideo.h
Normal file
21
src/win32/win32polyvideo.h
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "win32basevideo.h"
|
||||||
|
#include "c_cvars.h"
|
||||||
|
#include "rendering/polyrenderer/backend/poly_framebuffer.h"
|
||||||
|
|
||||||
|
EXTERN_CVAR(Bool, fullscreen)
|
||||||
|
|
||||||
|
class Win32PolyVideo : public Win32BaseVideo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void Shutdown() override
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
DFrameBuffer *CreateFrameBuffer() override
|
||||||
|
{
|
||||||
|
auto fb = new PolyFrameBuffer(m_hMonitor, fullscreen);
|
||||||
|
return fb;
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in a new issue