Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First pass of OpenGL rendering pipeline #1201

Draft
wants to merge 76 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
76e3162
Basic GL Pipeline init for Windows
dpogue Apr 9, 2022
f9ffe45
Fixup formatting in pl3DPipeline
dpogue Aug 12, 2023
490b552
Move IClearShadowSlaves to pl3DPipeline
dpogue Apr 10, 2022
5130a17
Fix duplicate plProfile counter linking
dpogue Jun 5, 2022
8cb3541
Draw to the screen. Not accurately, but it does draw.
dpogue Aug 17, 2015
c26e14c
Actually rendering something coherent now
dpogue Jul 13, 2014
d804dd1
Fix vertex colours
dpogue Jul 13, 2014
31ce785
Minor fixes that don't actually make it render correctly
dpogue Oct 17, 2014
e8b258b
Fix geometry rendering
dpogue Oct 19, 2014
9e99e62
Fix rendering: Solid geometry renders correctly now
dpogue Oct 20, 2014
4a1524e
Refactor some GL pipeline stuff
dpogue Jan 4, 2015
2b231c6
Generate per-material shaders for GLPipeline
dpogue Jan 8, 2015
2f217c5
Totally hacky, but working, textures
dpogue Jun 7, 2015
d2bab10
Handling initial blend modes and Z flags
dpogue Jun 24, 2015
7c86cdb
Better shader generation pipeline
dpogue Jun 29, 2015
d026385
Slightly hacky fixes for texture blending
dpogue Jul 1, 2015
1dd688c
Properly handle multiple passes
dpogue Jul 1, 2015
7f71882
Properly using (some) layer colours
dpogue Jul 4, 2015
6a37645
Hacky temp fix for non-DXT textures
dpogue Jul 4, 2015
84b4963
Move some buffer stuff up to pl3DPipeline
dpogue Aug 30, 2015
a57a85e
DirectX & Metal side of moving the buffer code
dpogue Jun 7, 2022
ac85786
Refactor the texture loading
dpogue Jan 8, 2016
5902b6e
DirectX device stub for the texture stuff
dpogue Jun 8, 2022
264029d
Possibly working Envmaps
dpogue Jan 9, 2016
8c01b03
Fix the alpha blend textures
dpogue Jan 9, 2016
6e0bdd9
Implement quick & hacky Z-bias offset
dpogue Jan 10, 2016
3fb6173
Clean up GL context stuff when shutting down
dpogue Jun 8, 2022
0fed8d9
Add initial pass of GL runtime lighting
dpogue Aug 2, 2016
1ca82bd
Try to fix depth offsets
dpogue Sep 25, 2016
ce55c96
Initial work on GL Plate rendering
dpogue May 21, 2020
cbd6fb8
All the fun GL compat stuff for plates...
dpogue Jul 8, 2020
8aa4bb2
Fix crashes due to plate init before GL context
dpogue Jun 10, 2022
2640163
Check textures for refresh every frame
dpogue May 21, 2020
b3e56d7
Fix some rendering issues in plGLPipeline
dpogue Jul 4, 2020
35ed3b1
Fix for leaking VAOs
colincornaby Dec 24, 2020
fc88ee5
Version check VAO usage
dpogue Jun 10, 2022
ad384cc
Fix some rendering glitches
dpogue Dec 23, 2020
6a77293
Some initial stabs at rewriting the shaders
dpogue Dec 23, 2020
726c12c
Fix up some GL issues with skinned meshes
dpogue Dec 27, 2020
4d53e46
Working spot lights
dpogue Dec 28, 2020
6745013
Mostly working dynamic vertex buffers
dpogue Dec 28, 2020
4f54731
Always use the new vertex shader
dpogue Dec 28, 2020
de5ff06
Initial set of changes to get desktop OpenGL working
colincornaby Dec 28, 2020
571e906
Cache the matrix locations from the shader
dpogue Jan 2, 2021
e636d27
Cache the lamp uniforms too
dpogue Jan 2, 2021
4f1bd85
Don't force skinned meshes to be dynamic buffers
dpogue Jan 2, 2021
77c6cd3
Set up GL render targets with framebuffers
dpogue Jan 2, 2021
af32aec
GL pipeline cleanups
dpogue Jan 2, 2021
2dfd633
Try to get DynamicCamMaps working
dpogue Jan 2, 2021
bb3f93a
Fixes for plate GL state being wrong
dpogue Jan 2, 2021
dd68560
Remove (unused) dynamic vertex shader generation
dpogue Jan 2, 2021
2672510
Fixes for cull mode in GL
colincornaby Dec 2, 2021
d6d882e
Fix for z-fighting with physics bodies
colincornaby Dec 11, 2021
adb6764
Fix for alpha testing in fragment shader
colincornaby Dec 11, 2021
96066fa
Opacity based culling fixes
colincornaby Dec 13, 2021
c263289
Better fix for Z-fighting with hologram
colincornaby Dec 13, 2021
d8ab6a3
Fix for directional lighting
colincornaby Jan 2, 2022
cd36224
Hack in the same CPU skinning from DX for now
dpogue Jan 2, 2022
25d3e2f
Move Push/Pop Layer stuff to pl3DPipeline
dpogue Jul 2, 2022
fed4c61
Fix GL pipeline crash opening the KI
dpogue Dec 30, 2022
8256d82
Fix GL "too many blend modes" crash
dpogue Dec 30, 2022
34818b1
Add plGLVersion helper function for testing
dpogue Jan 9, 2023
f35843f
Initial pass of avatar rendering (with no textures)
dpogue Feb 19, 2023
4cdc8ca
OpenGL avatar clothing texture rendering
dpogue Feb 21, 2023
ce89be2
Fix EGL enumeration with mesa/nouveau
dpogue Apr 11, 2023
e47a458
plTextFont rendering for GL Pipeline
dpogue May 5, 2023
617741a
Fix linking transition opacity animation for GL
dpogue May 13, 2023
1530abc
Fix Relto crash with GL Pipeline
dpogue May 13, 2023
635cfdd
Fix awful font layout on GL pipeline
dpogue May 13, 2023
790174d
Disable dynamic shader creation by default
dpogue Jun 21, 2023
50998de
Remove dynamic shader system
dpogue Jun 21, 2023
02b6c5f
Reorganize platform GL context providers
dpogue Sep 9, 2023
efc7d7d
Identity-initialize all the GL device matrices
dpogue Sep 9, 2023
26cf71f
Clean up API boundary for plGLDevice
dpogue Sep 9, 2023
cbfcf03
Clean up some buffer ref casts
dpogue Sep 9, 2023
2dd8afc
Resolve some GL Pipeline memory leaks & crashes
dpogue Apr 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions Sources/Plasma/Apps/plClient/Mac-Cocoa/main.mm
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,6 @@

// System Frameworks
#import <Cocoa/Cocoa.h>
#ifdef PLASMA_PIPELINE_GL
#import <OpenGL/gl.h>
#endif
#ifdef PLASMA_PIPELINE_METAL
#import <Metal/Metal.h>
#endif
Expand Down
302 changes: 296 additions & 6 deletions Sources/Plasma/FeatureLib/pfDXPipeline/plDXDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,39 @@ You can contact Cyan Worlds, Inc. by email [email protected]
#define WEAK_ERROR_CHECK( cond ) cond
#endif


/// Macros for getting/setting data in a D3D vertex buffer
template<typename T>
static inline void inlCopy(uint8_t*& src, uint8_t*& dst)
{
T* src_ptr = reinterpret_cast<T*>(src);
T* dst_ptr = reinterpret_cast<T*>(dst);
*dst_ptr = *src_ptr;
src += sizeof(T);
dst += sizeof(T);
}

static inline void inlCopy(const uint8_t*& src, uint8_t*& dst, size_t sz)
{
memcpy(dst, src, sz);
src += sz;
dst += sz;
}

template<typename T, size_t N>
static inline void inlSkip(uint8_t*& src)
{
src += sizeof(T) * N;
}


static D3DMATRIX d3dIdentityMatrix{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
};


D3DMATRIX& IMatrix44ToD3DMatrix(D3DMATRIX& dst, const hsMatrix44& src)
{
if (src.fFlags & hsMatrix44::kIsIdent) {
Expand Down Expand Up @@ -104,11 +129,8 @@ D3DMATRIX& IMatrix44ToD3DMatrix(D3DMATRIX& dst, const hsMatrix44& src)


plDXDevice::plDXDevice()
: fD3DDevice(nullptr),
fD3DMainSurface(nullptr),
fD3DDepthSurface(nullptr),
fD3DBackBuff(nullptr),
fCurrCullMode(D3DCULL_CW)
: fD3DDevice(), fD3DMainSurface(), fD3DDepthSurface(), fD3DBackBuff(),
fCurrCullMode(D3DCULL_CW), fManagedAlloced(), fAllocUnManaged()
{
}

Expand Down Expand Up @@ -163,6 +185,257 @@ void plDXDevice::SetViewport()
WEAK_ERROR_CHECK(fD3DDevice->SetViewport(&vp));
}

/**
* Calculate the vertex stride from the given format.
*/
static uint32_t GetBufferFormatSize(uint8_t format)
{
uint32_t size = sizeof(float) * 6 + sizeof(uint32_t) * 2; // Position and normal, and two packed colors
dpogue marked this conversation as resolved.
Show resolved Hide resolved

switch (format & plGBufferGroup::kSkinWeightMask) {
case plGBufferGroup::kSkinNoWeights:
break;
case plGBufferGroup::kSkin1Weight:
size += sizeof(float);
break;
default:
hsAssert(false, "Invalid skin weight value in GetBufferFormatSize()");
}

size += sizeof(float) * 3 * plGBufferGroup::CalcNumUVs(format);

return size;
}

void plDXDevice::SetupVertexBufferRef(plGBufferGroup* owner, uint32_t idx, VertexBufferRef* vRef)
{
// Initialize to nullptr, in case something goes wrong.
vRef->fD3DBuffer = nullptr;

uint8_t format = owner->GetVertexFormat();

// All indexed skinning is currently done on CPU, so the source data
// will have indices, but we strip them out for the D3D buffer.
if (format & plGBufferGroup::kSkinIndices) {
format &= ~(plGBufferGroup::kSkinWeightMask | plGBufferGroup::kSkinIndices);
format |= plGBufferGroup::kSkinNoWeights; // Should do nothing, but just in case...
vRef->SetSkinned(true);
vRef->SetVolatile(true);
}

uint32_t vertSize = GetBufferFormatSize(format); // vertex stride
uint32_t numVerts = owner->GetVertBufferCount(idx);

vRef->fDevice = fD3DDevice;

vRef->fOwner = owner;
vRef->fCount = numVerts;
vRef->fVertexSize = vertSize;
vRef->fFormat = format;
vRef->fRefTime = 0;

vRef->SetDirty(true);
vRef->SetRebuiltSinceUsed(true);
vRef->fData = nullptr;

vRef->SetVolatile(vRef->Volatile() || owner->AreVertsVolatile());

vRef->fIndex = idx;

owner->SetVertexBufferRef(idx, vRef);
hsRefCnt_SafeUnRef(vRef);
}

void plDXDevice::CheckStaticVertexBuffer(VertexBufferRef* vRef, plGBufferGroup* owner, uint32_t idx)
{
if (fAllocUnManaged)
return;

hsAssert(!vRef->Volatile(), "Creating a managed vertex buffer for a volatile buffer ref");

if (!vRef->fD3DBuffer) {
// Okay, haven't done this one.
DWORD fvfFormat = fPipeline->IGetBufferD3DFormat(vRef->fFormat);

D3DPOOL poolType = D3DPOOL_MANAGED;
//DWORD usage = D3DUSAGE_WRITEONLY;
DWORD usage = 0;
const int numVerts = vRef->fCount;
const int vertSize = vRef->fVertexSize;
fManagedAlloced = true;

if (FAILED(fD3DDevice->CreateVertexBuffer(numVerts * vertSize,
usage,
fvfFormat,
poolType,
&vRef->fD3DBuffer, nullptr)))
{
hsAssert(false, "CreateVertexBuffer() call failed!");
vRef->fD3DBuffer = nullptr;
return;
}
PROFILE_POOL_MEM(poolType, numVerts * vertSize, true, ST_LITERAL("VtxBuff"));

// Fill in the vertex data.
FillStaticVertexBufferRef(vRef, owner, idx);

// This is currently a no op, but this would let the buffer know it can
// unload the system memory copy, since we have a managed version now.
owner->PurgeVertBuffer(idx);
}
}

void plDXDevice::FillStaticVertexBufferRef(VertexBufferRef* ref, plGBufferGroup* group, uint32_t idx)
{
IDirect3DVertexBuffer9* vertexBuff = ref->fD3DBuffer;

if (!vertexBuff)
// We most likely already warned about this earlier, best to just quietly return now
return;

const uint32_t vertSize = ref->fVertexSize;
const uint32_t vertStart = group->GetVertBufferStart(idx) * vertSize;
const uint32_t size = group->GetVertBufferEnd(idx) * vertSize - vertStart;
if (!size)
return;

/// Lock the buffer
uint8_t* ptr;
if (FAILED(vertexBuff->Lock(vertStart, size, (void **)&ptr, group->AreVertsVolatile() ? D3DLOCK_DISCARD : 0)))
hsAssert(false, "Failed to lock vertex buffer for writing");

if (ref->fData) {
memcpy(ptr, ref->fData + vertStart, size);
} else {
hsAssert(0 == vertStart, "Offsets on non-interleaved data not supported");
hsAssert(group->GetVertBufferCount(idx) * vertSize == size, "Trailing dead space on non-interleaved data not supported");

const uint32_t vertSmallSize = group->GetVertexLiteStride() - sizeof(hsPoint3) * 2;
uint8_t* srcVPtr = group->GetVertBufferData(idx);
plGBufferColor* const srcCPtr = group->GetColorBufferData(idx);

const int numCells = group->GetNumCells(idx);
for (int i = 0; i < numCells; i++) {
plGBufferCell *cell = group->GetCell(idx, i);

if (cell->fColorStart == uint32_t(-1)) {
/// Interleaved, do straight copy
memcpy(ptr, srcVPtr + cell->fVtxStart, cell->fLength * vertSize);
ptr += cell->fLength * vertSize;
} else {
/// Separated, gotta interleave
uint8_t* tempVPtr = srcVPtr + cell->fVtxStart;
plGBufferColor* tempCPtr = srcCPtr + cell->fColorStart;

for (int j = 0; j < cell->fLength; j++) {
memcpy(ptr, tempVPtr, sizeof(hsPoint3) * 2);
ptr += sizeof(hsPoint3) * 2;
tempVPtr += sizeof(hsPoint3) * 2;

memcpy(ptr, &tempCPtr->fDiffuse, sizeof(uint32_t));
ptr += sizeof(uint32_t);
memcpy(ptr, &tempCPtr->fSpecular, sizeof(uint32_t));
ptr += sizeof(uint32_t);

memcpy(ptr, tempVPtr, vertSmallSize);
ptr += vertSmallSize;
tempVPtr += vertSmallSize;
tempCPtr++;
}
}
}
}

/// Unlock and clean up
vertexBuff->Unlock();
ref->SetRebuiltSinceUsed(true);
ref->SetDirty(false);
}

void plDXDevice::FillVolatileVertexBufferRef(VertexBufferRef* ref, plGBufferGroup* group, uint32_t idx)
{
uint8_t* dst = ref->fData;
uint8_t* src = group->GetVertBufferData(idx);

size_t uvChanSize = plGBufferGroup::CalcNumUVs(group->GetVertexFormat()) * sizeof(float) * 3;
uint8_t numWeights = (group->GetVertexFormat() & plGBufferGroup::kSkinWeightMask) >> 4;

for (uint32_t i = 0; i < ref->fCount; ++i) {
inlCopy<hsPoint3>(src, dst); // pre-pos
src += numWeights * sizeof(float); // weights
if (group->GetVertexFormat() & plGBufferGroup::kSkinIndices)
inlSkip<uint32_t, 1>(src); // indices
inlCopy<hsVector3>(src, dst); // pre-normal
inlCopy<uint32_t>(src, dst); // diffuse
inlCopy<uint32_t>(src, dst); // specular

// UVWs
memcpy(dst, src, uvChanSize);
src += uvChanSize;
dst += uvChanSize;
}
}

void plDXDevice::SetupIndexBufferRef(plGBufferGroup* owner, uint32_t idx, IndexBufferRef* iRef)
{
uint32_t numIndices = owner->GetIndexBufferCount(idx);
iRef->fCount = numIndices;
iRef->fOwner = owner;
iRef->fIndex = idx;
iRef->fRefTime = 0;

iRef->SetDirty(true);
iRef->SetRebuiltSinceUsed(true);

owner->SetIndexBufferRef(idx, iRef);
hsRefCnt_SafeUnRef(iRef);

iRef->SetVolatile(owner->AreIdxVolatile());
}

void plDXDevice::CheckIndexBuffer(IndexBufferRef* iRef)
{
if (!iRef->fD3DBuffer && iRef->fCount) {
D3DPOOL poolType = fAllocUnManaged ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED;
DWORD usage = D3DUSAGE_WRITEONLY;
iRef->SetVolatile(false);
if (FAILED(fD3DDevice->CreateIndexBuffer(sizeof(uint16_t) * iRef->fCount,
usage,
D3DFMT_INDEX16,
poolType,
&iRef->fD3DBuffer, nullptr)))
{
hsAssert(false, "CreateIndexBuffer() call failed!");
iRef->fD3DBuffer = nullptr;
return;
}
PROFILE_POOL_MEM(poolType, sizeof(uint16_t) * iRef->fCount, true, ST_LITERAL("IndexBuff"));

iRef->fPoolType = poolType;
iRef->SetDirty(true);
iRef->SetRebuiltSinceUsed(true);
}
}

void plDXDevice::FillIndexBufferRef(IndexBufferRef* iRef, plGBufferGroup* owner, uint32_t idx)
{
uint32_t startIdx = owner->GetIndexBufferStart(idx);
uint32_t size = (owner->GetIndexBufferEnd(idx) - startIdx) * sizeof(uint16_t);
if (!size)
return;

DWORD lockFlags = iRef->Volatile() ? D3DLOCK_DISCARD : 0;
uint16_t* destPtr = nullptr;
if (FAILED(iRef->fD3DBuffer->Lock(startIdx * sizeof(uint16_t), size, (void **)&destPtr, lockFlags))) {
hsAssert(false, "Cannot lock index buffer for writing");
return;
}

memcpy(destPtr, owner->GetIndexBufferData(idx) + startIdx, size);

iRef->fD3DBuffer->Unlock();
iRef->SetDirty(false);
}

void plDXDevice::SetProjectionMatrix(const hsMatrix44& src)
{
Expand Down Expand Up @@ -195,3 +468,20 @@ ST::string plDXDevice::GetErrorString() const
{
return fPipeline->fSettings.fErrorStr;
}

void plDXDevice::BeginAllocUnManaged()
{
// Flush out all managed resources to make room for unmanaged resources.
fD3DDevice->EvictManagedResources();

fManagedAlloced = false;
fAllocUnManaged = true; // we're currently only allocating POOL_DEFAULT
}

void plDXDevice::EndAllocUnManaged()
{
fAllocUnManaged = false;

// Flush the (should be empty) resource manager to reset its internal allocation pool.
fD3DDevice->EvictManagedResources();
}
Loading