mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-01-19 13:51:16 +00:00
Upload models to GPU before rendering (#272)
This commit is contained in:
parent
9ebeda5c0e
commit
c8b8035de8
@ -192,6 +192,91 @@ Uint32 OpenGL15Renderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
|||||||
return (Uint32) (m_textures.size() - 1);
|
return (Uint32) (m_textures.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLMeshCacheEntry GLUploadMesh(const MeshGroup& meshGroup)
|
||||||
|
{
|
||||||
|
GLMeshCacheEntry cache{&meshGroup, meshGroup.version};
|
||||||
|
|
||||||
|
cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT;
|
||||||
|
|
||||||
|
std::vector<D3DRMVERTEX> vertices;
|
||||||
|
if (cache.flat) {
|
||||||
|
FlattenSurfaces(
|
||||||
|
meshGroup.vertices.data(),
|
||||||
|
meshGroup.vertices.size(),
|
||||||
|
meshGroup.indices.data(),
|
||||||
|
meshGroup.indices.size(),
|
||||||
|
meshGroup.texture != nullptr,
|
||||||
|
vertices,
|
||||||
|
cache.indices
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
vertices.assign(meshGroup.vertices.begin(), meshGroup.vertices.end());
|
||||||
|
cache.indices.assign(meshGroup.indices.begin(), meshGroup.indices.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
cache.texcoords.resize(vertices.size());
|
||||||
|
std::transform(vertices.begin(), vertices.end(), cache.texcoords.begin(), [](const D3DRMVERTEX& v) {
|
||||||
|
return v.texCoord;
|
||||||
|
});
|
||||||
|
cache.positions.resize(vertices.size());
|
||||||
|
std::transform(vertices.begin(), vertices.end(), cache.positions.begin(), [](const D3DRMVERTEX& v) {
|
||||||
|
return v.position;
|
||||||
|
});
|
||||||
|
cache.normals.resize(vertices.size());
|
||||||
|
std::transform(vertices.begin(), vertices.end(), cache.normals.begin(), [](const D3DRMVERTEX& v) {
|
||||||
|
return v.normal;
|
||||||
|
});
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GLMeshDestroyContext {
|
||||||
|
OpenGL15Renderer* renderer;
|
||||||
|
Uint32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
void OpenGL15Renderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
|
||||||
|
{
|
||||||
|
auto* ctx = new GLMeshDestroyContext{this, id};
|
||||||
|
mesh->AddDestroyCallback(
|
||||||
|
[](IDirect3DRMObject*, void* arg) {
|
||||||
|
auto* ctx = static_cast<GLMeshDestroyContext*>(arg);
|
||||||
|
ctx->renderer->m_meshs[ctx->id].meshGroup = nullptr;
|
||||||
|
delete ctx;
|
||||||
|
},
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 OpenGL15Renderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
|
||||||
|
{
|
||||||
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
|
auto& cache = m_meshs[i];
|
||||||
|
if (cache.meshGroup == meshGroup) {
|
||||||
|
if (cache.version != meshGroup->version) {
|
||||||
|
cache = std::move(GLUploadMesh(*meshGroup));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newCache = GLUploadMesh(*meshGroup);
|
||||||
|
|
||||||
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
|
auto& cache = m_meshs[i];
|
||||||
|
if (!cache.meshGroup) {
|
||||||
|
cache = std::move(newCache);
|
||||||
|
AddMeshDestroyCallback(i, mesh);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meshs.push_back(std::move(newCache));
|
||||||
|
AddMeshDestroyCallback((Uint32) (m_meshs.size() - 1), mesh);
|
||||||
|
return (Uint32) (m_meshs.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD OpenGL15Renderer::GetWidth()
|
DWORD OpenGL15Renderer::GetWidth()
|
||||||
{
|
{
|
||||||
return m_width;
|
return m_width;
|
||||||
@ -306,10 +391,7 @@ HRESULT OpenGL15Renderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OpenGL15Renderer::SubmitDraw(
|
void OpenGL15Renderer::SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
DWORD meshId,
|
||||||
const size_t vertexCount,
|
|
||||||
const DWORD* indices,
|
|
||||||
const size_t indexCount,
|
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -323,47 +405,9 @@ void OpenGL15Renderer::SubmitDraw(
|
|||||||
glLoadMatrixf(&mvMatrix[0][0]);
|
glLoadMatrixf(&mvMatrix[0][0]);
|
||||||
glEnable(GL_NORMALIZE);
|
glEnable(GL_NORMALIZE);
|
||||||
|
|
||||||
std::vector<D3DRMVERTEX> newVertices;
|
|
||||||
std::vector<DWORD> newIndices;
|
|
||||||
if (appearance.flat) {
|
|
||||||
glShadeModel(GL_FLAT);
|
|
||||||
// FIXME move this to a one time mesh upload stage
|
|
||||||
FlattenSurfaces(
|
|
||||||
vertices,
|
|
||||||
vertexCount,
|
|
||||||
indices,
|
|
||||||
indexCount,
|
|
||||||
appearance.textureId != NO_TEXTURE_ID,
|
|
||||||
newVertices,
|
|
||||||
newIndices
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
glShadeModel(GL_SMOOTH);
|
|
||||||
newVertices.assign(vertices, vertices + vertexCount);
|
|
||||||
newIndices.assign(indices, indices + indexCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bind texture if present
|
|
||||||
std::vector<TexCoord> texcoords;
|
|
||||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
|
||||||
auto& tex = m_textures[appearance.textureId];
|
|
||||||
glEnable(GL_TEXTURE_2D);
|
|
||||||
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
|
|
||||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
texcoords.resize(newVertices.size());
|
|
||||||
std::transform(newVertices.begin(), newVertices.end(), texcoords.begin(), [](const D3DRMVERTEX& v) {
|
|
||||||
return v.texCoord;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
glDisable(GL_TEXTURE_2D);
|
|
||||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
glColor4ub(appearance.color.r, appearance.color.g, appearance.color.b, appearance.color.a);
|
||||||
|
|
||||||
float shininess = appearance.shininess;
|
float shininess = appearance.shininess * m_shininessFactor;
|
||||||
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
|
glMaterialf(GL_FRONT, GL_SHININESS, shininess);
|
||||||
if (shininess != 0.0f) {
|
if (shininess != 0.0f) {
|
||||||
GLfloat whiteSpec[] = {shininess, shininess, shininess, shininess};
|
GLfloat whiteSpec[] = {shininess, shininess, shininess, shininess};
|
||||||
@ -374,29 +418,36 @@ void OpenGL15Renderer::SubmitDraw(
|
|||||||
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
glMaterialfv(GL_FRONT, GL_SPECULAR, noSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<D3DVECTOR> positions;
|
auto& mesh = m_meshs[meshId];
|
||||||
positions.resize(newVertices.size());
|
|
||||||
std::transform(newVertices.begin(), newVertices.end(), positions.begin(), [](const D3DRMVERTEX& v) {
|
|
||||||
return v.position;
|
|
||||||
});
|
|
||||||
std::vector<D3DVECTOR> normals;
|
|
||||||
normals.resize(newVertices.size());
|
|
||||||
std::transform(newVertices.begin(), newVertices.end(), normals.begin(), [](const D3DRMVERTEX& v) {
|
|
||||||
return v.normal;
|
|
||||||
});
|
|
||||||
|
|
||||||
glEnableClientState(GL_VERTEX_ARRAY);
|
if (mesh.flat) {
|
||||||
glVertexPointer(3, GL_FLOAT, 0, positions.data());
|
glShadeModel(GL_FLAT);
|
||||||
|
}
|
||||||
glEnableClientState(GL_NORMAL_ARRAY);
|
else {
|
||||||
glNormalPointer(GL_FLOAT, 0, normals.data());
|
glShadeModel(GL_SMOOTH);
|
||||||
|
|
||||||
if (appearance.textureId != NO_TEXTURE_ID) {
|
|
||||||
glTexCoordPointer(2, GL_FLOAT, 0, texcoords.data());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bind texture if present
|
||||||
|
if (appearance.textureId != NO_TEXTURE_ID) {
|
||||||
|
auto& tex = m_textures[appearance.textureId];
|
||||||
|
glEnable(GL_TEXTURE_2D);
|
||||||
|
glBindTexture(GL_TEXTURE_2D, tex.glTextureId);
|
||||||
|
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
glTexCoordPointer(2, GL_FLOAT, 0, mesh.texcoords.data());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glDisable(GL_TEXTURE_2D);
|
||||||
|
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glVertexPointer(3, GL_FLOAT, 0, mesh.positions.data());
|
||||||
|
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
glNormalPointer(GL_FLOAT, 0, mesh.normals.data());
|
||||||
|
|
||||||
// Draw triangles
|
// Draw triangles
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(newIndices.size()), GL_UNSIGNED_INT, newIndices.data());
|
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(mesh.indices.size()), GL_UNSIGNED_INT, mesh.indices.data());
|
||||||
|
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -91,76 +91,6 @@ struct ScopedShader {
|
|||||||
void release() { ptr = nullptr; }
|
void release() { ptr = nullptr; }
|
||||||
};
|
};
|
||||||
|
|
||||||
SDL_GPUTexture* CreateTextureFromSurface(
|
|
||||||
SDL_GPUDevice* device,
|
|
||||||
SDL_GPUTransferBuffer* transferBuffer,
|
|
||||||
SDL_Surface* surface
|
|
||||||
)
|
|
||||||
{
|
|
||||||
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888)};
|
|
||||||
if (!surf.ptr) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Uint32 dataSize = surf.ptr->pitch * surf.ptr->h;
|
|
||||||
|
|
||||||
SDL_GPUTextureCreateInfo textureInfo = {};
|
|
||||||
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
|
|
||||||
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
|
||||||
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
|
||||||
textureInfo.width = surf.ptr->w;
|
|
||||||
textureInfo.height = surf.ptr->h;
|
|
||||||
textureInfo.layer_count_or_depth = 1;
|
|
||||||
textureInfo.num_levels = 1;
|
|
||||||
ScopedTexture texture{device, SDL_CreateGPUTexture(device, &textureInfo)};
|
|
||||||
if (!texture.ptr) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture (%s)", SDL_GetError());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* transferData = SDL_MapGPUTransferBuffer(device, transferBuffer, false);
|
|
||||||
if (!transferData) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer (%s)", SDL_GetError());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(transferData, surf.ptr->pixels, dataSize);
|
|
||||||
SDL_UnmapGPUTransferBuffer(device, transferBuffer);
|
|
||||||
|
|
||||||
SDL_GPUTextureTransferInfo transferRegionInfo = {};
|
|
||||||
transferRegionInfo.transfer_buffer = transferBuffer;
|
|
||||||
SDL_GPUTextureRegion textureRegion = {};
|
|
||||||
textureRegion.texture = texture.ptr;
|
|
||||||
textureRegion.w = surf.ptr->w;
|
|
||||||
textureRegion.h = surf.ptr->h;
|
|
||||||
textureRegion.d = 1;
|
|
||||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(device);
|
|
||||||
if (!cmdbuf) {
|
|
||||||
SDL_LogError(
|
|
||||||
LOG_CATEGORY_MINIWIN,
|
|
||||||
"SDL_AcquireGPUCommandBuffer in CreateTextureFromSurface failed (%s)",
|
|
||||||
SDL_GetError()
|
|
||||||
);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
SDL_GPUCopyPass* pass = SDL_BeginGPUCopyPass(cmdbuf);
|
|
||||||
SDL_UploadToGPUTexture(pass, &transferRegionInfo, &textureRegion, false);
|
|
||||||
|
|
||||||
SDL_EndGPUCopyPass(pass);
|
|
||||||
if (!SDL_SubmitGPUCommandBuffer(cmdbuf)) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_SubmitGPUCommandBuffer (%s)", SDL_GetError());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto texptr = texture.ptr;
|
|
||||||
|
|
||||||
// Release texture ownership so caller can manage it safely
|
|
||||||
texture.release();
|
|
||||||
|
|
||||||
return texptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device, bool depthWrite)
|
static SDL_GPUGraphicsPipeline* InitializeGraphicsPipeline(SDL_GPUDevice* device, bool depthWrite)
|
||||||
{
|
{
|
||||||
const SDL_GPUShaderCreateInfo* vertexCreateInfo =
|
const SDL_GPUShaderCreateInfo* vertexCreateInfo =
|
||||||
@ -325,24 +255,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ABGR8888);
|
|
||||||
if (!dummySurface) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
if (!SDL_LockSurface(dummySurface)) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to lock surface: %s", SDL_GetError());
|
|
||||||
SDL_DestroySurface(dummySurface);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
((Uint32*) dummySurface->pixels)[0] = 0xFFFFFFFF;
|
|
||||||
|
|
||||||
ScopedTexture dummyTexture{device.ptr, CreateTextureFromSurface(device.ptr, uploadBuffer.ptr, dummySurface)};
|
|
||||||
SDL_DestroySurface(dummySurface);
|
|
||||||
if (!dummyTexture.ptr) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create texture from surface");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
SDL_GPUSamplerCreateInfo samplerInfo = {};
|
SDL_GPUSamplerCreateInfo samplerInfo = {};
|
||||||
samplerInfo.min_filter = SDL_GPU_FILTER_LINEAR;
|
samplerInfo.min_filter = SDL_GPU_FILTER_LINEAR;
|
||||||
samplerInfo.mag_filter = SDL_GPU_FILTER_LINEAR;
|
samplerInfo.mag_filter = SDL_GPU_FILTER_LINEAR;
|
||||||
@ -364,7 +276,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
|||||||
transparentPipeline.ptr,
|
transparentPipeline.ptr,
|
||||||
transferTexture.ptr,
|
transferTexture.ptr,
|
||||||
depthTexture.ptr,
|
depthTexture.ptr,
|
||||||
dummyTexture.ptr,
|
|
||||||
sampler.ptr,
|
sampler.ptr,
|
||||||
uploadBuffer.ptr,
|
uploadBuffer.ptr,
|
||||||
downloadBuffer.ptr
|
downloadBuffer.ptr
|
||||||
@ -376,7 +287,6 @@ Direct3DRMRenderer* Direct3DRMSDL3GPURenderer::Create(DWORD width, DWORD height)
|
|||||||
transparentPipeline.release();
|
transparentPipeline.release();
|
||||||
transferTexture.release();
|
transferTexture.release();
|
||||||
depthTexture.release();
|
depthTexture.release();
|
||||||
dummyTexture.release();
|
|
||||||
sampler.release();
|
sampler.release();
|
||||||
uploadBuffer.release();
|
uploadBuffer.release();
|
||||||
downloadBuffer.release();
|
downloadBuffer.release();
|
||||||
@ -392,15 +302,29 @@ Direct3DRMSDL3GPURenderer::Direct3DRMSDL3GPURenderer(
|
|||||||
SDL_GPUGraphicsPipeline* transparentPipeline,
|
SDL_GPUGraphicsPipeline* transparentPipeline,
|
||||||
SDL_GPUTexture* transferTexture,
|
SDL_GPUTexture* transferTexture,
|
||||||
SDL_GPUTexture* depthTexture,
|
SDL_GPUTexture* depthTexture,
|
||||||
SDL_GPUTexture* dummyTexture,
|
|
||||||
SDL_GPUSampler* sampler,
|
SDL_GPUSampler* sampler,
|
||||||
SDL_GPUTransferBuffer* uploadBuffer,
|
SDL_GPUTransferBuffer* uploadBuffer,
|
||||||
SDL_GPUTransferBuffer* downloadBuffer
|
SDL_GPUTransferBuffer* downloadBuffer
|
||||||
)
|
)
|
||||||
: m_width(width), m_height(height), m_device(device), m_opaquePipeline(opaquePipeline),
|
: m_width(width), m_height(height), m_device(device), m_opaquePipeline(opaquePipeline),
|
||||||
m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture),
|
m_transparentPipeline(transparentPipeline), m_transferTexture(transferTexture), m_depthTexture(depthTexture),
|
||||||
m_dummyTexture(dummyTexture), m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer)
|
m_sampler(sampler), m_uploadBuffer(uploadBuffer), m_downloadBuffer(downloadBuffer)
|
||||||
{
|
{
|
||||||
|
SDL_Surface* dummySurface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_ABGR8888);
|
||||||
|
if (!dummySurface) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to create surface: %s", SDL_GetError());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!SDL_LockSurface(dummySurface)) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "Failed to lock surface: %s", SDL_GetError());
|
||||||
|
SDL_DestroySurface(dummySurface);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
((Uint32*) dummySurface->pixels)[0] = 0xFFFFFFFF;
|
||||||
|
SDL_UnlockSurface(dummySurface);
|
||||||
|
|
||||||
|
m_dummyTexture = CreateTextureFromSurface(dummySurface);
|
||||||
|
SDL_DestroySurface(dummySurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
|
Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
|
||||||
@ -412,10 +336,12 @@ Direct3DRMSDL3GPURenderer::~Direct3DRMSDL3GPURenderer()
|
|||||||
SDL_ReleaseGPUSampler(m_device, m_sampler);
|
SDL_ReleaseGPUSampler(m_device, m_sampler);
|
||||||
SDL_ReleaseGPUTexture(m_device, m_dummyTexture);
|
SDL_ReleaseGPUTexture(m_device, m_dummyTexture);
|
||||||
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
|
SDL_ReleaseGPUTexture(m_device, m_depthTexture);
|
||||||
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
|
|
||||||
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
|
SDL_ReleaseGPUTexture(m_device, m_transferTexture);
|
||||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline);
|
SDL_ReleaseGPUGraphicsPipeline(m_device, m_opaquePipeline);
|
||||||
SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline);
|
SDL_ReleaseGPUGraphicsPipeline(m_device, m_transparentPipeline);
|
||||||
|
if (m_uploadFence) {
|
||||||
|
SDL_ReleaseGPUFence(m_device, m_uploadFence);
|
||||||
|
}
|
||||||
SDL_DestroyGPUDevice(m_device);
|
SDL_DestroyGPUDevice(m_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -436,6 +362,19 @@ void Direct3DRMSDL3GPURenderer::SetProjection(const D3DRMMATRIX4D& projection, D
|
|||||||
memcpy(&m_uniforms.projection, projection, sizeof(D3DRMMATRIX4D));
|
memcpy(&m_uniforms.projection, projection, sizeof(D3DRMMATRIX4D));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Direct3DRMSDL3GPURenderer::WaitForPendingUpload()
|
||||||
|
{
|
||||||
|
if (!m_uploadFence) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bool success = SDL_WaitForGPUFences(m_device, true, &m_uploadFence, 1);
|
||||||
|
SDL_ReleaseGPUFence(m_device, m_uploadFence);
|
||||||
|
m_uploadFence = nullptr;
|
||||||
|
if (!success) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct SDLTextureDestroyContext {
|
struct SDLTextureDestroyContext {
|
||||||
Direct3DRMSDL3GPURenderer* renderer;
|
Direct3DRMSDL3GPURenderer* renderer;
|
||||||
Uint32 id;
|
Uint32 id;
|
||||||
@ -459,6 +398,69 @@ void Direct3DRMSDL3GPURenderer::AddTextureDestroyCallback(Uint32 id, IDirect3DRM
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_GPUTexture* Direct3DRMSDL3GPURenderer::CreateTextureFromSurface(SDL_Surface* surface)
|
||||||
|
{
|
||||||
|
ScopedSurface surf{SDL_ConvertSurface(surface, SDL_PIXELFORMAT_ABGR8888)};
|
||||||
|
if (!surf.ptr) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_ConvertSurface (%s)", SDL_GetError());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Uint32 dataSize = surf.ptr->pitch * surf.ptr->h;
|
||||||
|
|
||||||
|
SDL_GPUTextureCreateInfo textureInfo = {};
|
||||||
|
textureInfo.type = SDL_GPU_TEXTURETYPE_2D;
|
||||||
|
textureInfo.format = SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM;
|
||||||
|
textureInfo.usage = SDL_GPU_TEXTUREUSAGE_SAMPLER;
|
||||||
|
textureInfo.width = surf.ptr->w;
|
||||||
|
textureInfo.height = surf.ptr->h;
|
||||||
|
textureInfo.layer_count_or_depth = 1;
|
||||||
|
textureInfo.num_levels = 1;
|
||||||
|
ScopedTexture texture{m_device, SDL_CreateGPUTexture(m_device, &textureInfo)};
|
||||||
|
if (!texture.ptr) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUTexture (%s)", SDL_GetError());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
SDL_GPUTransferBuffer* transferBuffer = GetUploadBuffer(dataSize);
|
||||||
|
|
||||||
|
void* transferData = SDL_MapGPUTransferBuffer(m_device, transferBuffer, false);
|
||||||
|
if (!transferData) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer (%s)", SDL_GetError());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
memcpy(transferData, surf.ptr->pixels, dataSize);
|
||||||
|
SDL_UnmapGPUTransferBuffer(m_device, transferBuffer);
|
||||||
|
|
||||||
|
SDL_GPUTextureTransferInfo transferRegionInfo = {};
|
||||||
|
transferRegionInfo.transfer_buffer = transferBuffer;
|
||||||
|
SDL_GPUTextureRegion textureRegion = {};
|
||||||
|
textureRegion.texture = texture.ptr;
|
||||||
|
textureRegion.w = surf.ptr->w;
|
||||||
|
textureRegion.h = surf.ptr->h;
|
||||||
|
textureRegion.d = 1;
|
||||||
|
|
||||||
|
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||||
|
if (!cmdbuf) {
|
||||||
|
SDL_LogError(
|
||||||
|
LOG_CATEGORY_MINIWIN,
|
||||||
|
"SDL_AcquireGPUCommandBuffer in CreateTextureFromSurface failed (%s)",
|
||||||
|
SDL_GetError()
|
||||||
|
);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
SDL_GPUCopyPass* pass = SDL_BeginGPUCopyPass(cmdbuf);
|
||||||
|
SDL_UploadToGPUTexture(pass, &transferRegionInfo, &textureRegion, false);
|
||||||
|
SDL_EndGPUCopyPass(pass);
|
||||||
|
m_uploadFence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
|
||||||
|
|
||||||
|
auto texptr = texture.ptr;
|
||||||
|
|
||||||
|
// Release texture ownership so caller can manage it safely
|
||||||
|
texture.release();
|
||||||
|
|
||||||
|
return texptr;
|
||||||
|
}
|
||||||
|
|
||||||
Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
||||||
{
|
{
|
||||||
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
|
auto texture = static_cast<Direct3DRMTextureImpl*>(iTexture);
|
||||||
@ -470,7 +472,7 @@ Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
|||||||
if (tex.texture == texture) {
|
if (tex.texture == texture) {
|
||||||
if (tex.version != texture->m_version) {
|
if (tex.version != texture->m_version) {
|
||||||
SDL_ReleaseGPUTexture(m_device, tex.gpuTexture);
|
SDL_ReleaseGPUTexture(m_device, tex.gpuTexture);
|
||||||
tex.gpuTexture = CreateTextureFromSurface(m_device, GetUploadBuffer(surf->w * surf->h * 4), surf);
|
tex.gpuTexture = CreateTextureFromSurface(surf);
|
||||||
if (!tex.gpuTexture) {
|
if (!tex.gpuTexture) {
|
||||||
return NO_TEXTURE_ID;
|
return NO_TEXTURE_ID;
|
||||||
}
|
}
|
||||||
@ -480,7 +482,7 @@ Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_GPUTexture* newTex = CreateTextureFromSurface(m_device, GetUploadBuffer(surf->w * surf->h * 4), surf);
|
SDL_GPUTexture* newTex = CreateTextureFromSurface(surf);
|
||||||
if (!newTex) {
|
if (!newTex) {
|
||||||
return NO_TEXTURE_ID;
|
return NO_TEXTURE_ID;
|
||||||
}
|
}
|
||||||
@ -499,6 +501,123 @@ Uint32 Direct3DRMSDL3GPURenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
|||||||
return (Uint32) (m_textures.size() - 1);
|
return (Uint32) (m_textures.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL3MeshCache Direct3DRMSDL3GPURenderer::UploadMesh(const MeshGroup& meshGroup)
|
||||||
|
{
|
||||||
|
std::vector<D3DRMVERTEX> flatVertices;
|
||||||
|
if (meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT) {
|
||||||
|
std::vector<D3DRMVERTEX> newVertices;
|
||||||
|
std::vector<DWORD> newIndices;
|
||||||
|
FlattenSurfaces(
|
||||||
|
meshGroup.vertices.data(),
|
||||||
|
meshGroup.vertices.size(),
|
||||||
|
meshGroup.indices.data(),
|
||||||
|
meshGroup.indices.size(),
|
||||||
|
meshGroup.texture != nullptr,
|
||||||
|
newVertices,
|
||||||
|
newIndices
|
||||||
|
);
|
||||||
|
for (DWORD& index : newIndices) {
|
||||||
|
flatVertices.push_back(newVertices[index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// TODO handle indexed verticies on GPU
|
||||||
|
for (int i = 0; i < meshGroup.indices.size(); ++i) {
|
||||||
|
flatVertices.push_back(meshGroup.vertices[meshGroup.indices[i]]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
|
||||||
|
bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
|
||||||
|
bufferCreateInfo.size = sizeof(D3DRMVERTEX) * flatVertices.size();
|
||||||
|
SDL_GPUBuffer* vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
||||||
|
if (!vertexBuffer) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer failed (%s)", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_GPUTransferBuffer* uploadBuffer = GetUploadBuffer(sizeof(D3DRMVERTEX) * flatVertices.size());
|
||||||
|
if (!uploadBuffer) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
D3DRMVERTEX* transferData = (D3DRMVERTEX*) SDL_MapGPUTransferBuffer(m_device, uploadBuffer, false);
|
||||||
|
if (!transferData) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer returned NULL buffer (%s)", SDL_GetError());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(transferData, flatVertices.data(), sizeof(D3DRMVERTEX) * flatVertices.size());
|
||||||
|
SDL_UnmapGPUTransferBuffer(m_device, uploadBuffer);
|
||||||
|
|
||||||
|
SDL_GPUTransferBufferLocation transferLocation = {};
|
||||||
|
transferLocation.transfer_buffer = uploadBuffer;
|
||||||
|
|
||||||
|
SDL_GPUBufferRegion bufferRegion = {};
|
||||||
|
bufferRegion.buffer = vertexBuffer;
|
||||||
|
bufferRegion.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * flatVertices.size());
|
||||||
|
|
||||||
|
// Upload the transfer data to the vertex buffer
|
||||||
|
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||||
|
if (!cmdbuf) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in SubmitDraw failed (%s)", SDL_GetError());
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
|
||||||
|
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
|
||||||
|
SDL_EndGPUCopyPass(copyPass);
|
||||||
|
m_uploadFence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
|
||||||
|
|
||||||
|
return {&meshGroup, meshGroup.version, vertexBuffer, flatVertices.size()};
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SDLMeshDestroyContext {
|
||||||
|
Direct3DRMSDL3GPURenderer* renderer;
|
||||||
|
Uint32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Direct3DRMSDL3GPURenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
|
||||||
|
{
|
||||||
|
auto* ctx = new SDLMeshDestroyContext{this, id};
|
||||||
|
mesh->AddDestroyCallback(
|
||||||
|
[](IDirect3DRMObject*, void* arg) {
|
||||||
|
auto* ctx = static_cast<SDLMeshDestroyContext*>(arg);
|
||||||
|
auto& cache = ctx->renderer->m_meshs[ctx->id];
|
||||||
|
SDL_ReleaseGPUBuffer(ctx->renderer->m_device, cache.vertexBuffer);
|
||||||
|
cache.meshGroup = nullptr;
|
||||||
|
delete ctx;
|
||||||
|
},
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 Direct3DRMSDL3GPURenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
|
||||||
|
{
|
||||||
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
|
auto& cache = m_meshs[i];
|
||||||
|
if (cache.meshGroup == meshGroup) {
|
||||||
|
if (cache.version != meshGroup->version) {
|
||||||
|
SDL_ReleaseGPUBuffer(m_device, cache.vertexBuffer);
|
||||||
|
cache = std::move(UploadMesh(*meshGroup));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newCache = UploadMesh(*meshGroup);
|
||||||
|
|
||||||
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
|
auto& cache = m_meshs[i];
|
||||||
|
if (!cache.meshGroup) {
|
||||||
|
cache = std::move(newCache);
|
||||||
|
AddMeshDestroyCallback(i, mesh);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meshs.push_back(std::move(newCache));
|
||||||
|
AddMeshDestroyCallback((Uint32) (m_meshs.size() - 1), mesh);
|
||||||
|
return (Uint32) (m_meshs.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD Direct3DRMSDL3GPURenderer::GetWidth()
|
DWORD Direct3DRMSDL3GPURenderer::GetWidth()
|
||||||
{
|
{
|
||||||
return m_width;
|
return m_width;
|
||||||
@ -527,42 +646,6 @@ const char* Direct3DRMSDL3GPURenderer::GetName()
|
|||||||
return "SDL3 GPU HAL";
|
return "SDL3 GPU HAL";
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
|
||||||
{
|
|
||||||
if (!DDBackBuffer) {
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D));
|
|
||||||
|
|
||||||
// Clear color and depth targets
|
|
||||||
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
|
||||||
colorTargetInfo.texture = m_transferTexture;
|
|
||||||
colorTargetInfo.clear_color = {0, 0, 0, 0};
|
|
||||||
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
|
||||||
|
|
||||||
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
|
|
||||||
depthStencilTargetInfo.texture = m_depthTexture;
|
|
||||||
depthStencilTargetInfo.clear_depth = 0.0f;
|
|
||||||
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
|
||||||
|
|
||||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
|
||||||
if (!cmdbuf) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in BeginFrame failed (%s)", SDL_GetError());
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
|
|
||||||
SDL_EndGPURenderPass(renderPass);
|
|
||||||
|
|
||||||
if (!SDL_SubmitGPUCommandBuffer(cmdbuf)) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_SubmitGPUCommandBuffer failed (%s)", SDL_GetError());
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
return DD_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNormalMatrix4x4)
|
void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNormalMatrix4x4)
|
||||||
{
|
{
|
||||||
for (int row = 0; row < 3; ++row) {
|
for (int row = 0; row < 3; ++row) {
|
||||||
@ -578,6 +661,7 @@ void PackNormalMatrix(const Matrix3x3& normalMatrix3x3, D3DRMMATRIX4D& packedNor
|
|||||||
|
|
||||||
SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
|
SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
|
||||||
{
|
{
|
||||||
|
WaitForPendingUpload();
|
||||||
if (m_uploadBufferSize < size) {
|
if (m_uploadBufferSize < size) {
|
||||||
SDL_ReleaseGPUTransferBuffer(m_device, m_uploadBuffer);
|
SDL_ReleaseGPUTransferBuffer(m_device, m_uploadBuffer);
|
||||||
|
|
||||||
@ -599,140 +683,75 @@ SDL_GPUTransferBuffer* Direct3DRMSDL3GPURenderer::GetUploadBuffer(size_t size)
|
|||||||
return m_uploadBuffer;
|
return m_uploadBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HRESULT Direct3DRMSDL3GPURenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
||||||
|
{
|
||||||
|
if (!DDBackBuffer) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&m_viewMatrix, viewMatrix, sizeof(D3DRMMATRIX4D));
|
||||||
|
|
||||||
|
// Clear color and depth targets
|
||||||
|
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
||||||
|
colorTargetInfo.texture = m_transferTexture;
|
||||||
|
colorTargetInfo.clear_color = {0, 0, 0, 0};
|
||||||
|
colorTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||||
|
|
||||||
|
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
|
||||||
|
depthStencilTargetInfo.texture = m_depthTexture;
|
||||||
|
depthStencilTargetInfo.clear_depth = 0.0f;
|
||||||
|
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_CLEAR;
|
||||||
|
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
|
||||||
|
|
||||||
|
m_cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
||||||
|
if (!m_cmdbuf) {
|
||||||
|
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in BeginFrame failed (%s)", SDL_GetError());
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_renderPass = SDL_BeginGPURenderPass(m_cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
|
||||||
|
SDL_BindGPUGraphicsPipeline(m_renderPass, m_opaquePipeline);
|
||||||
|
|
||||||
|
return DD_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
void Direct3DRMSDL3GPURenderer::SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
DWORD meshId,
|
||||||
const size_t vertexCount,
|
|
||||||
const DWORD* indices,
|
|
||||||
const size_t indexCount,
|
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
// TODO only switch piplinen after all opaque's have been rendered
|
||||||
|
SDL_BindGPUGraphicsPipeline(m_renderPass, appearance.color.a == 255 ? m_opaquePipeline : m_transparentPipeline);
|
||||||
|
|
||||||
D3DRMMATRIX4D worldViewMatrix;
|
D3DRMMATRIX4D worldViewMatrix;
|
||||||
MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix);
|
MultiplyMatrix(worldViewMatrix, worldMatrix, m_viewMatrix);
|
||||||
memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D));
|
memcpy(&m_uniforms.worldViewMatrix, worldViewMatrix, sizeof(D3DRMMATRIX4D));
|
||||||
PackNormalMatrix(normalMatrix, m_uniforms.normalMatrix);
|
PackNormalMatrix(normalMatrix, m_uniforms.normalMatrix);
|
||||||
m_fragmentShadingData.color = appearance.color;
|
m_fragmentShadingData.color = appearance.color;
|
||||||
m_fragmentShadingData.shininess = appearance.shininess;
|
m_fragmentShadingData.shininess = appearance.shininess * m_shininessFactor;
|
||||||
|
bool useTexture = appearance.textureId != NO_TEXTURE_ID;
|
||||||
|
m_fragmentShadingData.useTexture = appearance.textureId != NO_TEXTURE_ID;
|
||||||
|
|
||||||
std::vector<D3DRMVERTEX> flatVertices;
|
auto& mesh = m_meshs[meshId];
|
||||||
if (appearance.flat) {
|
|
||||||
std::vector<D3DRMVERTEX> newVertices;
|
|
||||||
std::vector<DWORD> newIndices;
|
|
||||||
// FIXME move this to a one time mesh upload stage
|
|
||||||
FlattenSurfaces(
|
|
||||||
vertices,
|
|
||||||
vertexCount,
|
|
||||||
indices,
|
|
||||||
indexCount,
|
|
||||||
appearance.textureId != NO_TEXTURE_ID,
|
|
||||||
newVertices,
|
|
||||||
newIndices
|
|
||||||
);
|
|
||||||
for (DWORD& index : newIndices) {
|
|
||||||
flatVertices.push_back(newVertices[index]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// TODO handle indexed verticies on GPU
|
|
||||||
for (int i = 0; i < indexCount; ++i) {
|
|
||||||
flatVertices.push_back(vertices[indices[i]]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flatVertices.size() > m_vertexBufferCount) {
|
|
||||||
if (m_vertexBuffer) {
|
|
||||||
SDL_ReleaseGPUBuffer(m_device, m_vertexBuffer);
|
|
||||||
}
|
|
||||||
SDL_GPUBufferCreateInfo bufferCreateInfo = {};
|
|
||||||
bufferCreateInfo.usage = SDL_GPU_BUFFERUSAGE_VERTEX;
|
|
||||||
bufferCreateInfo.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * flatVertices.size());
|
|
||||||
m_vertexBuffer = SDL_CreateGPUBuffer(m_device, &bufferCreateInfo);
|
|
||||||
if (!m_vertexBuffer) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_CreateGPUBuffer failed (%s)", SDL_GetError());
|
|
||||||
}
|
|
||||||
m_vertexBufferCount = flatVertices.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
m_vertexCount = flatVertices.size();
|
|
||||||
|
|
||||||
SDL_GPUTransferBuffer* uploadBuffer = GetUploadBuffer(sizeof(D3DRMVERTEX) * m_vertexCount);
|
|
||||||
if (!uploadBuffer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
D3DRMVERTEX* transferData = (D3DRMVERTEX*) SDL_MapGPUTransferBuffer(m_device, uploadBuffer, false);
|
|
||||||
if (!transferData) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_MapGPUTransferBuffer returned NULL buffer (%s)", SDL_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(transferData, flatVertices.data(), m_vertexCount * sizeof(D3DRMVERTEX));
|
|
||||||
SDL_UnmapGPUTransferBuffer(m_device, uploadBuffer);
|
|
||||||
|
|
||||||
// Upload the transfer data to the vertex buffer
|
|
||||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
|
||||||
if (!cmdbuf) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in SubmitDraw failed (%s)", SDL_GetError());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
|
|
||||||
SDL_GPUTransferBufferLocation transferLocation = {};
|
|
||||||
transferLocation.transfer_buffer = uploadBuffer;
|
|
||||||
|
|
||||||
SDL_GPUBufferRegion bufferRegion = {};
|
|
||||||
bufferRegion.buffer = m_vertexBuffer;
|
|
||||||
bufferRegion.size = static_cast<Uint32>(sizeof(D3DRMVERTEX) * m_vertexCount);
|
|
||||||
|
|
||||||
SDL_UploadToGPUBuffer(copyPass, &transferLocation, &bufferRegion, false);
|
|
||||||
SDL_EndGPUCopyPass(copyPass);
|
|
||||||
|
|
||||||
// Render the graphics
|
// Render the graphics
|
||||||
SDL_GPUColorTargetInfo colorTargetInfo = {};
|
SDL_GPUTexture* texture = useTexture ? m_textures[appearance.textureId].gpuTexture : m_dummyTexture;
|
||||||
colorTargetInfo.texture = m_transferTexture;
|
SDL_GPUTextureSamplerBinding samplerBinding = {texture, m_sampler};
|
||||||
colorTargetInfo.load_op = SDL_GPU_LOADOP_LOAD;
|
SDL_BindGPUFragmentSamplers(m_renderPass, 0, &samplerBinding, 1);
|
||||||
|
SDL_PushGPUVertexUniformData(m_cmdbuf, 0, &m_uniforms, sizeof(m_uniforms));
|
||||||
SDL_GPUDepthStencilTargetInfo depthStencilTargetInfo = {};
|
SDL_PushGPUFragmentUniformData(m_cmdbuf, 0, &m_fragmentShadingData, sizeof(m_fragmentShadingData));
|
||||||
depthStencilTargetInfo.texture = m_depthTexture;
|
SDL_GPUBufferBinding vertexBufferBinding = {mesh.vertexBuffer};
|
||||||
depthStencilTargetInfo.load_op = SDL_GPU_LOADOP_LOAD;
|
SDL_BindGPUVertexBuffers(m_renderPass, 0, &vertexBufferBinding, 1);
|
||||||
depthStencilTargetInfo.store_op = SDL_GPU_STOREOP_STORE;
|
SDL_DrawGPUPrimitives(m_renderPass, mesh.vertexCount, 1, 0, 0);
|
||||||
|
|
||||||
SDL_GPURenderPass* renderPass = SDL_BeginGPURenderPass(cmdbuf, &colorTargetInfo, 1, &depthStencilTargetInfo);
|
|
||||||
SDL_BindGPUGraphicsPipeline(renderPass, appearance.color.a == 255 ? m_opaquePipeline : m_transparentPipeline);
|
|
||||||
|
|
||||||
m_fragmentShadingData.useTexture = appearance.textureId != NO_TEXTURE_ID;
|
|
||||||
SDL_GPUTextureSamplerBinding samplerBinding = {};
|
|
||||||
samplerBinding.texture =
|
|
||||||
m_fragmentShadingData.useTexture ? m_textures[appearance.textureId].gpuTexture : m_dummyTexture;
|
|
||||||
samplerBinding.sampler = m_sampler;
|
|
||||||
SDL_BindGPUFragmentSamplers(renderPass, 0, &samplerBinding, 1);
|
|
||||||
|
|
||||||
SDL_PushGPUVertexUniformData(cmdbuf, 0, &m_uniforms, sizeof(m_uniforms));
|
|
||||||
SDL_PushGPUFragmentUniformData(cmdbuf, 0, &m_fragmentShadingData, sizeof(m_fragmentShadingData));
|
|
||||||
|
|
||||||
if (m_vertexCount) {
|
|
||||||
SDL_GPUBufferBinding vertexBufferBinding = {};
|
|
||||||
vertexBufferBinding.buffer = m_vertexBuffer;
|
|
||||||
vertexBufferBinding.offset = 0;
|
|
||||||
SDL_BindGPUVertexBuffers(renderPass, 0, &vertexBufferBinding, 1);
|
|
||||||
SDL_DrawGPUPrimitives(renderPass, m_vertexCount, 1, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_EndGPURenderPass(renderPass);
|
|
||||||
|
|
||||||
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
|
|
||||||
if (!fence || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) {
|
|
||||||
if (fence) {
|
|
||||||
SDL_ReleaseGPUFence(m_device, fence);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
SDL_ReleaseGPUFence(m_device, fence);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
|
HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
|
||||||
{
|
{
|
||||||
|
SDL_EndGPURenderPass(m_renderPass);
|
||||||
|
m_renderPass = nullptr;
|
||||||
|
|
||||||
// Download rendered image
|
// Download rendered image
|
||||||
SDL_GPUTextureRegion region = {};
|
SDL_GPUTextureRegion region = {};
|
||||||
region.texture = m_transferTexture;
|
region.texture = m_transferTexture;
|
||||||
@ -742,23 +761,23 @@ HRESULT Direct3DRMSDL3GPURenderer::FinalizeFrame()
|
|||||||
SDL_GPUTextureTransferInfo transferInfo = {};
|
SDL_GPUTextureTransferInfo transferInfo = {};
|
||||||
transferInfo.transfer_buffer = m_downloadBuffer;
|
transferInfo.transfer_buffer = m_downloadBuffer;
|
||||||
|
|
||||||
SDL_GPUCommandBuffer* cmdbuf = SDL_AcquireGPUCommandBuffer(m_device);
|
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(m_cmdbuf);
|
||||||
if (!cmdbuf) {
|
|
||||||
SDL_LogError(LOG_CATEGORY_MINIWIN, "SDL_AcquireGPUCommandBuffer in FinalizeFrame failed (%s)", SDL_GetError());
|
|
||||||
return DDERR_GENERIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDL_GPUCopyPass* copyPass = SDL_BeginGPUCopyPass(cmdbuf);
|
|
||||||
SDL_DownloadFromGPUTexture(copyPass, ®ion, &transferInfo);
|
SDL_DownloadFromGPUTexture(copyPass, ®ion, &transferInfo);
|
||||||
SDL_EndGPUCopyPass(copyPass);
|
SDL_EndGPUCopyPass(copyPass);
|
||||||
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(cmdbuf);
|
|
||||||
if (!fence || !SDL_WaitForGPUFences(m_device, true, &fence, 1)) {
|
WaitForPendingUpload();
|
||||||
if (fence) {
|
|
||||||
SDL_ReleaseGPUFence(m_device, fence);
|
// Render the frame
|
||||||
}
|
SDL_GPUFence* fence = SDL_SubmitGPUCommandBufferAndAcquireFence(m_cmdbuf);
|
||||||
|
m_cmdbuf = nullptr;
|
||||||
|
if (!fence) {
|
||||||
return DDERR_GENERIC;
|
return DDERR_GENERIC;
|
||||||
}
|
}
|
||||||
|
bool success = SDL_WaitForGPUFences(m_device, true, &fence, 1);
|
||||||
SDL_ReleaseGPUFence(m_device, fence);
|
SDL_ReleaseGPUFence(m_device, fence);
|
||||||
|
if (!success) {
|
||||||
|
return DDERR_GENERIC;
|
||||||
|
}
|
||||||
void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadBuffer, false);
|
void* downloadedData = SDL_MapGPUTransferBuffer(m_device, m_downloadBuffer, false);
|
||||||
if (!downloadedData) {
|
if (!downloadedData) {
|
||||||
return DDERR_GENERIC;
|
return DDERR_GENERIC;
|
||||||
|
|||||||
@ -185,7 +185,7 @@ SDL_Color Direct3DRMSoftwareRenderer::ApplyLighting(
|
|||||||
|
|
||||||
if (appearance.shininess != 0.0f) {
|
if (appearance.shininess != 0.0f) {
|
||||||
// Using dotNL ignores view angle, but this matches DirectX 5 behavior.
|
// Using dotNL ignores view angle, but this matches DirectX 5 behavior.
|
||||||
float spec = std::pow(dotNL, appearance.shininess);
|
float spec = std::pow(dotNL, appearance.shininess * m_shininessFactor);
|
||||||
specular.r += spec * lightColor.r;
|
specular.r += spec * lightColor.r;
|
||||||
specular.g += spec * lightColor.g;
|
specular.g += spec * lightColor.g;
|
||||||
specular.b += spec * lightColor.b;
|
specular.b += spec * lightColor.b;
|
||||||
@ -439,6 +439,78 @@ Uint32 Direct3DRMSoftwareRenderer::GetTextureId(IDirect3DRMTexture* iTexture)
|
|||||||
return static_cast<Uint32>(m_textures.size() - 1);
|
return static_cast<Uint32>(m_textures.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MeshCache UploadMesh(const MeshGroup& meshGroup)
|
||||||
|
{
|
||||||
|
MeshCache cache{&meshGroup, meshGroup.version};
|
||||||
|
|
||||||
|
cache.flat = meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT;
|
||||||
|
|
||||||
|
std::vector<D3DRMVERTEX> vertices;
|
||||||
|
if (cache.flat) {
|
||||||
|
FlattenSurfaces(
|
||||||
|
meshGroup.vertices.data(),
|
||||||
|
meshGroup.vertices.size(),
|
||||||
|
meshGroup.indices.data(),
|
||||||
|
meshGroup.indices.size(),
|
||||||
|
meshGroup.texture != nullptr,
|
||||||
|
cache.vertices,
|
||||||
|
cache.indices
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cache.vertices.assign(meshGroup.vertices.begin(), meshGroup.vertices.end());
|
||||||
|
cache.indices.assign(meshGroup.indices.begin(), meshGroup.indices.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MeshDestroyContext {
|
||||||
|
Direct3DRMSoftwareRenderer* renderer;
|
||||||
|
Uint32 id;
|
||||||
|
};
|
||||||
|
|
||||||
|
void Direct3DRMSoftwareRenderer::AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh)
|
||||||
|
{
|
||||||
|
auto* ctx = new MeshDestroyContext{this, id};
|
||||||
|
mesh->AddDestroyCallback(
|
||||||
|
[](IDirect3DRMObject*, void* arg) {
|
||||||
|
auto* ctx = static_cast<MeshDestroyContext*>(arg);
|
||||||
|
ctx->renderer->m_meshs[ctx->id].meshGroup = nullptr;
|
||||||
|
delete ctx;
|
||||||
|
},
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint32 Direct3DRMSoftwareRenderer::GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup)
|
||||||
|
{
|
||||||
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
|
auto& cache = m_meshs[i];
|
||||||
|
if (cache.meshGroup == meshGroup) {
|
||||||
|
if (cache.version != meshGroup->version) {
|
||||||
|
cache = std::move(UploadMesh(*meshGroup));
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto newCache = UploadMesh(*meshGroup);
|
||||||
|
|
||||||
|
for (Uint32 i = 0; i < m_meshs.size(); ++i) {
|
||||||
|
auto& cache = m_meshs[i];
|
||||||
|
if (!cache.meshGroup) {
|
||||||
|
cache = std::move(newCache);
|
||||||
|
AddMeshDestroyCallback(i, mesh);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_meshs.push_back(std::move(newCache));
|
||||||
|
AddMeshDestroyCallback((Uint32) (m_meshs.size() - 1), mesh);
|
||||||
|
return (Uint32) (m_meshs.size() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
DWORD Direct3DRMSoftwareRenderer::GetWidth()
|
DWORD Direct3DRMSoftwareRenderer::GetWidth()
|
||||||
{
|
{
|
||||||
return m_width;
|
return m_width;
|
||||||
@ -483,10 +555,7 @@ HRESULT Direct3DRMSoftwareRenderer::BeginFrame(const D3DRMMATRIX4D& viewMatrix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Direct3DRMSoftwareRenderer::SubmitDraw(
|
void Direct3DRMSoftwareRenderer::SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
DWORD meshId,
|
||||||
const size_t vertexCount,
|
|
||||||
const DWORD* indices,
|
|
||||||
const size_t indexCount,
|
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -495,29 +564,12 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
|
|||||||
D3DRMMATRIX4D mvMatrix;
|
D3DRMMATRIX4D mvMatrix;
|
||||||
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
|
MultiplyMatrix(mvMatrix, worldMatrix, m_viewMatrix);
|
||||||
|
|
||||||
std::vector<D3DRMVERTEX> newVertices;
|
auto& mesh = m_meshs[meshId];
|
||||||
std::vector<DWORD> newIndices;
|
|
||||||
if (appearance.flat) {
|
|
||||||
// FIXME move this to a one time mesh upload stage
|
|
||||||
FlattenSurfaces(
|
|
||||||
vertices,
|
|
||||||
vertexCount,
|
|
||||||
indices,
|
|
||||||
indexCount,
|
|
||||||
appearance.textureId != NO_TEXTURE_ID,
|
|
||||||
newVertices,
|
|
||||||
newIndices
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newVertices.assign(vertices, vertices + vertexCount);
|
|
||||||
newIndices.assign(indices, indices + indexCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pre-transform all vertex positions and normals
|
// Pre-transform all vertex positions and normals
|
||||||
std::vector<D3DRMVERTEX> transformedVerts(newVertices.size());
|
std::vector<D3DRMVERTEX> transformedVerts(mesh.vertices.size());
|
||||||
for (size_t i = 0; i < newVertices.size(); ++i) {
|
for (size_t i = 0; i < mesh.vertices.size(); ++i) {
|
||||||
const D3DRMVERTEX& src = newVertices[i];
|
const D3DRMVERTEX& src = mesh.vertices[i];
|
||||||
D3DRMVERTEX& dst = transformedVerts[i];
|
D3DRMVERTEX& dst = transformedVerts[i];
|
||||||
dst.position = TransformPoint(src.position, mvMatrix);
|
dst.position = TransformPoint(src.position, mvMatrix);
|
||||||
// TODO defer normal transformation til lighting to allow culling first
|
// TODO defer normal transformation til lighting to allow culling first
|
||||||
@ -526,9 +578,11 @@ void Direct3DRMSoftwareRenderer::SubmitDraw(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assemble triangles using index buffer
|
// Assemble triangles using index buffer
|
||||||
for (size_t i = 0; i + 2 < newIndices.size(); i += 3) {
|
for (size_t i = 0; i + 2 < mesh.indices.size(); i += 3) {
|
||||||
DrawTriangleClipped(
|
DrawTriangleClipped(
|
||||||
{transformedVerts[newIndices[i]], transformedVerts[newIndices[i + 1]], transformedVerts[newIndices[i + 2]]},
|
{transformedVerts[mesh.indices[i]],
|
||||||
|
transformedVerts[mesh.indices[i + 1]],
|
||||||
|
transformedVerts[mesh.indices[i + 2]]},
|
||||||
appearance
|
appearance
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -117,7 +117,12 @@ HRESULT Direct3DRMMeshImpl::SetGroupColor(DWORD groupIndex, D3DCOLOR color)
|
|||||||
return DDERR_INVALIDPARAMS;
|
return DDERR_INVALIDPARAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_groups[groupIndex].color = color;
|
m_groups[groupIndex].color = {
|
||||||
|
static_cast<Uint8>((color >> 16) & 0xFF),
|
||||||
|
static_cast<Uint8>((color >> 8) & 0xFF),
|
||||||
|
static_cast<Uint8>((color >> 0) & 0xFF),
|
||||||
|
static_cast<Uint8>((color >> 24) & 0xFF)
|
||||||
|
};
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +132,9 @@ HRESULT Direct3DRMMeshImpl::SetGroupColorRGB(DWORD groupIndex, float r, float g,
|
|||||||
return DDERR_INVALIDPARAMS;
|
return DDERR_INVALIDPARAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
D3DCOLOR color = (0xFF << 24) | (static_cast<BYTE>(r * 255.0f) << 16) | (static_cast<BYTE>(g * 255.0f) << 8) |
|
m_groups[groupIndex]
|
||||||
(static_cast<BYTE>(b * 255.0f));
|
.color = {static_cast<Uint8>(r * 255.0f), static_cast<Uint8>(g * 255.0f), static_cast<Uint8>(b * 255.0f), 255};
|
||||||
|
|
||||||
m_groups[groupIndex].color = color;
|
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +143,9 @@ D3DCOLOR Direct3DRMMeshImpl::GetGroupColor(D3DRMGROUPINDEX index)
|
|||||||
if (index < 0 || index >= static_cast<int>(m_groups.size())) {
|
if (index < 0 || index >= static_cast<int>(m_groups.size())) {
|
||||||
return 0xFFFFFFFF;
|
return 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
return m_groups[index].color;
|
|
||||||
|
const SDL_Color& color = m_groups[index].color;
|
||||||
|
return (color.a << 24) | (color.r << 16) | (color.g << 8) | color.b;
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Direct3DRMMeshImpl::SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material)
|
HRESULT Direct3DRMMeshImpl::SetGroupMaterial(DWORD groupIndex, IDirect3DRMMaterial* material)
|
||||||
@ -171,6 +177,7 @@ HRESULT Direct3DRMMeshImpl::SetGroupTexture(DWORD groupIndex, IDirect3DRMTexture
|
|||||||
|
|
||||||
texture->AddRef();
|
texture->AddRef();
|
||||||
group.texture = texture;
|
group.texture = texture;
|
||||||
|
group.version++;
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,7 +236,10 @@ HRESULT Direct3DRMMeshImpl::SetGroupQuality(DWORD groupIndex, D3DRMRENDERQUALITY
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_groups[groupIndex].quality = quality;
|
auto& group = m_groups[groupIndex];
|
||||||
|
group.quality = quality;
|
||||||
|
group.version++;
|
||||||
|
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -248,7 +258,8 @@ HRESULT Direct3DRMMeshImpl::SetVertices(DWORD groupIndex, int offset, int count,
|
|||||||
return DDERR_INVALIDPARAMS;
|
return DDERR_INVALIDPARAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& vertList = m_groups[groupIndex].vertices;
|
auto& group = m_groups[groupIndex];
|
||||||
|
auto& vertList = group.vertices;
|
||||||
|
|
||||||
if (offset + count > static_cast<int>(vertList.size())) {
|
if (offset + count > static_cast<int>(vertList.size())) {
|
||||||
vertList.resize(offset + count);
|
vertList.resize(offset + count);
|
||||||
@ -258,6 +269,8 @@ HRESULT Direct3DRMMeshImpl::SetVertices(DWORD groupIndex, int offset, int count,
|
|||||||
|
|
||||||
UpdateBox();
|
UpdateBox();
|
||||||
|
|
||||||
|
group.version++;
|
||||||
|
|
||||||
return DD_OK;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -180,13 +180,31 @@ void ExtractFrustumPlanes(const D3DRMMATRIX4D& m)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsBoxInFrustum(const D3DVECTOR corners[8], const Plane planes[6])
|
bool IsMeshInFrustum(Direct3DRMMeshImpl* mesh, const D3DRMMATRIX4D& worldMatrix)
|
||||||
{
|
{
|
||||||
|
D3DRMBOX box;
|
||||||
|
mesh->GetBox(&box);
|
||||||
|
|
||||||
|
D3DVECTOR boxCorners[8] = {
|
||||||
|
{box.min.x, box.min.y, box.min.z},
|
||||||
|
{box.min.x, box.min.y, box.max.z},
|
||||||
|
{box.min.x, box.max.y, box.min.z},
|
||||||
|
{box.min.x, box.max.y, box.max.z},
|
||||||
|
{box.max.x, box.min.y, box.min.z},
|
||||||
|
{box.max.x, box.min.y, box.max.z},
|
||||||
|
{box.max.x, box.max.y, box.min.z},
|
||||||
|
{box.max.x, box.max.y, box.max.z},
|
||||||
|
};
|
||||||
|
|
||||||
|
for (D3DVECTOR& corner : boxCorners) {
|
||||||
|
corner = TransformPoint(corner, worldMatrix);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 6; ++i) {
|
for (int i = 0; i < 6; ++i) {
|
||||||
int out = 0;
|
int out = 0;
|
||||||
for (int j = 0; j < 8; ++j) {
|
for (int j = 0; j < 8; ++j) {
|
||||||
float dist = planes[i].normal.x * corners[j].x + planes[i].normal.y * corners[j].y +
|
float dist = frustumPlanes[i].normal.x * boxCorners[j].x + frustumPlanes[i].normal.y * boxCorners[j].y +
|
||||||
planes[i].normal.z * corners[j].z + planes[i].d;
|
frustumPlanes[i].normal.z * boxCorners[j].z + frustumPlanes[i].d;
|
||||||
if (dist < 0.0f) {
|
if (dist < 0.0f) {
|
||||||
++out;
|
++out;
|
||||||
}
|
}
|
||||||
@ -210,8 +228,6 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D
|
|||||||
Matrix3x3 worldMatrixInvert;
|
Matrix3x3 worldMatrixInvert;
|
||||||
D3DRMMatrixInvertForNormal(worldMatrixInvert, worldMatrix);
|
D3DRMMatrixInvertForNormal(worldMatrixInvert, worldMatrix);
|
||||||
|
|
||||||
const float shininessFactor = m_renderer->GetShininessFactor();
|
|
||||||
|
|
||||||
IDirect3DRMVisualArray* visuals = nullptr;
|
IDirect3DRMVisualArray* visuals = nullptr;
|
||||||
frame->GetVisuals(&visuals);
|
frame->GetVisuals(&visuals);
|
||||||
DWORD n = visuals->GetSize();
|
DWORD n = visuals->GetSize();
|
||||||
@ -230,63 +246,24 @@ void Direct3DRMViewportImpl::CollectMeshesFromFrame(IDirect3DRMFrame* frame, D3D
|
|||||||
|
|
||||||
Direct3DRMMeshImpl* mesh = nullptr;
|
Direct3DRMMeshImpl* mesh = nullptr;
|
||||||
visual->QueryInterface(IID_IDirect3DRMMesh, (void**) &mesh);
|
visual->QueryInterface(IID_IDirect3DRMMesh, (void**) &mesh);
|
||||||
if (!mesh) {
|
if (mesh) {
|
||||||
visual->Release();
|
if (IsMeshInFrustum(mesh, worldMatrix)) {
|
||||||
continue;
|
DWORD groupCount = mesh->GetGroupCount();
|
||||||
}
|
for (DWORD gi = 0; gi < groupCount; ++gi) {
|
||||||
|
const MeshGroup& meshGroup = mesh->GetGroup(gi);
|
||||||
D3DRMBOX box;
|
m_renderer->SubmitDraw(
|
||||||
mesh->GetBox(&box);
|
m_renderer->GetMeshId(mesh, &meshGroup),
|
||||||
D3DVECTOR boxCorners[8] = {
|
worldMatrix,
|
||||||
{box.min.x, box.min.y, box.min.z},
|
worldMatrixInvert,
|
||||||
{box.min.x, box.min.y, box.max.z},
|
{meshGroup.color,
|
||||||
{box.min.x, box.max.y, box.min.z},
|
meshGroup.material ? meshGroup.material->GetPower() : 0.0f,
|
||||||
{box.min.x, box.max.y, box.max.z},
|
meshGroup.texture ? m_renderer->GetTextureId(meshGroup.texture) : NO_TEXTURE_ID,
|
||||||
{box.max.x, box.min.y, box.min.z},
|
meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT}
|
||||||
{box.max.x, box.min.y, box.max.z},
|
);
|
||||||
{box.max.x, box.max.y, box.min.z},
|
}
|
||||||
{box.max.x, box.max.y, box.max.z},
|
}
|
||||||
};
|
|
||||||
for (D3DVECTOR& boxCorner : boxCorners) {
|
|
||||||
boxCorner = TransformPoint(boxCorner, worldMatrix);
|
|
||||||
}
|
|
||||||
if (!IsBoxInFrustum(boxCorners, frustumPlanes)) {
|
|
||||||
mesh->Release();
|
mesh->Release();
|
||||||
visual->Release();
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD groupCount = mesh->GetGroupCount();
|
|
||||||
for (DWORD gi = 0; gi < groupCount; ++gi) {
|
|
||||||
const MeshGroup& meshGroup = mesh->GetGroup(gi);
|
|
||||||
|
|
||||||
Uint32 textureId = NO_TEXTURE_ID;
|
|
||||||
if (meshGroup.texture) {
|
|
||||||
textureId = m_renderer->GetTextureId(meshGroup.texture);
|
|
||||||
}
|
|
||||||
|
|
||||||
float shininess = 0.0f;
|
|
||||||
if (meshGroup.material) {
|
|
||||||
shininess = meshGroup.material->GetPower() * shininessFactor;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_renderer->SubmitDraw(
|
|
||||||
meshGroup.vertices.data(),
|
|
||||||
meshGroup.vertices.size(),
|
|
||||||
meshGroup.indices.data(),
|
|
||||||
meshGroup.indices.size(),
|
|
||||||
worldMatrix,
|
|
||||||
worldMatrixInvert,
|
|
||||||
{{static_cast<Uint8>((meshGroup.color >> 16) & 0xFF),
|
|
||||||
static_cast<Uint8>((meshGroup.color >> 8) & 0xFF),
|
|
||||||
static_cast<Uint8>((meshGroup.color >> 0) & 0xFF),
|
|
||||||
static_cast<Uint8>((meshGroup.color >> 24) & 0xFF)},
|
|
||||||
shininess,
|
|
||||||
textureId,
|
|
||||||
meshGroup.quality == D3DRMRENDER_FLAT || meshGroup.quality == D3DRMRENDER_UNLITFLAT}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
mesh->Release();
|
|
||||||
visual->Release();
|
visual->Release();
|
||||||
}
|
}
|
||||||
visuals->Release();
|
visuals->Release();
|
||||||
|
|||||||
@ -6,11 +6,12 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
struct MeshGroup {
|
struct MeshGroup {
|
||||||
D3DCOLOR color = 0xFFFFFFFF;
|
SDL_Color color = {0xFF, 0xFF, 0xFF, 0xFF};
|
||||||
IDirect3DRMTexture* texture = nullptr;
|
IDirect3DRMTexture* texture = nullptr;
|
||||||
IDirect3DRMMaterial* material = nullptr;
|
IDirect3DRMMaterial* material = nullptr;
|
||||||
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
|
D3DRMRENDERQUALITY quality = D3DRMRENDER_GOURAUD;
|
||||||
int vertexPerFace = 0;
|
int vertexPerFace = 0;
|
||||||
|
int version = 0;
|
||||||
std::vector<D3DRMVERTEX> vertices;
|
std::vector<D3DRMVERTEX> vertices;
|
||||||
std::vector<unsigned int> indices;
|
std::vector<unsigned int> indices;
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "d3drmmesh_impl.h"
|
||||||
#include "mathutils.h"
|
#include "mathutils.h"
|
||||||
#include "miniwin/d3drm.h"
|
#include "miniwin/d3drm.h"
|
||||||
#include "miniwin/miniwindevice.h"
|
#include "miniwin/miniwindevice.h"
|
||||||
@ -35,16 +36,14 @@ class Direct3DRMRenderer : public IDirect3DDevice2 {
|
|||||||
virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
|
virtual void PushLights(const SceneLight* vertices, size_t count) = 0;
|
||||||
virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0;
|
virtual void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) = 0;
|
||||||
virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0;
|
virtual Uint32 GetTextureId(IDirect3DRMTexture* texture) = 0;
|
||||||
|
virtual Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) = 0;
|
||||||
virtual DWORD GetWidth() = 0;
|
virtual DWORD GetWidth() = 0;
|
||||||
virtual DWORD GetHeight() = 0;
|
virtual DWORD GetHeight() = 0;
|
||||||
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
|
virtual void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) = 0;
|
||||||
virtual const char* GetName() = 0;
|
virtual const char* GetName() = 0;
|
||||||
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
|
virtual HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) = 0;
|
||||||
virtual void SubmitDraw(
|
virtual void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
DWORD meshId,
|
||||||
const size_t vertexCount,
|
|
||||||
const DWORD* indices,
|
|
||||||
const size_t indexCount,
|
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
|
|||||||
@ -16,6 +16,16 @@ struct GLTextureCacheEntry {
|
|||||||
GLuint glTextureId;
|
GLuint glTextureId;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct GLMeshCacheEntry {
|
||||||
|
const MeshGroup* meshGroup;
|
||||||
|
int version;
|
||||||
|
bool flat;
|
||||||
|
std::vector<D3DVECTOR> positions;
|
||||||
|
std::vector<D3DVECTOR> normals;
|
||||||
|
std::vector<TexCoord> texcoords;
|
||||||
|
std::vector<DWORD> indices;
|
||||||
|
};
|
||||||
|
|
||||||
class OpenGL15Renderer : public Direct3DRMRenderer {
|
class OpenGL15Renderer : public Direct3DRMRenderer {
|
||||||
public:
|
public:
|
||||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
||||||
@ -24,16 +34,14 @@ class OpenGL15Renderer : public Direct3DRMRenderer {
|
|||||||
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
void PushLights(const SceneLight* lightsArray, size_t count) override;
|
||||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||||
|
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||||
DWORD GetWidth() override;
|
DWORD GetWidth() override;
|
||||||
DWORD GetHeight() override;
|
DWORD GetHeight() override;
|
||||||
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
void GetDesc(D3DDEVICEDESC* halDesc, D3DDEVICEDESC* helDesc) override;
|
||||||
const char* GetName() override;
|
const char* GetName() override;
|
||||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||||
void SubmitDraw(
|
void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
DWORD meshId,
|
||||||
const size_t vertexCount,
|
|
||||||
const DWORD* indices,
|
|
||||||
const size_t indexCount,
|
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -42,7 +50,9 @@ class OpenGL15Renderer : public Direct3DRMRenderer {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||||
|
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||||
std::vector<GLTextureCacheEntry> m_textures;
|
std::vector<GLTextureCacheEntry> m_textures;
|
||||||
|
std::vector<GLMeshCacheEntry> m_meshs;
|
||||||
D3DRMMATRIX4D m_viewMatrix;
|
D3DRMMATRIX4D m_viewMatrix;
|
||||||
D3DRMMATRIX4D m_projection;
|
D3DRMMATRIX4D m_projection;
|
||||||
SDL_Surface* m_renderedImage;
|
SDL_Surface* m_renderedImage;
|
||||||
|
|||||||
@ -34,12 +34,20 @@ struct SDL3TextureCache {
|
|||||||
SDL_GPUTexture* gpuTexture;
|
SDL_GPUTexture* gpuTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct SDL3MeshCache {
|
||||||
|
const MeshGroup* meshGroup;
|
||||||
|
int version;
|
||||||
|
SDL_GPUBuffer* vertexBuffer;
|
||||||
|
size_t vertexCount;
|
||||||
|
};
|
||||||
|
|
||||||
class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
||||||
public:
|
public:
|
||||||
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
static Direct3DRMRenderer* Create(DWORD width, DWORD height);
|
||||||
~Direct3DRMSDL3GPURenderer() override;
|
~Direct3DRMSDL3GPURenderer() override;
|
||||||
void PushLights(const SceneLight* vertices, size_t count) override;
|
void PushLights(const SceneLight* vertices, size_t count) override;
|
||||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||||
|
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||||
DWORD GetWidth() override;
|
DWORD GetWidth() override;
|
||||||
DWORD GetHeight() override;
|
DWORD GetHeight() override;
|
||||||
@ -47,10 +55,7 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
|||||||
const char* GetName() override;
|
const char* GetName() override;
|
||||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||||
void SubmitDraw(
|
void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
DWORD meshId,
|
||||||
const size_t vertexCount,
|
|
||||||
const DWORD* indices,
|
|
||||||
const size_t indexCount,
|
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -66,25 +71,27 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
|||||||
SDL_GPUGraphicsPipeline* transparentPipeline,
|
SDL_GPUGraphicsPipeline* transparentPipeline,
|
||||||
SDL_GPUTexture* transferTexture,
|
SDL_GPUTexture* transferTexture,
|
||||||
SDL_GPUTexture* depthTexture,
|
SDL_GPUTexture* depthTexture,
|
||||||
SDL_GPUTexture* dummyTexture,
|
|
||||||
SDL_GPUSampler* sampler,
|
SDL_GPUSampler* sampler,
|
||||||
SDL_GPUTransferBuffer* uploadBuffer,
|
SDL_GPUTransferBuffer* uploadBuffer,
|
||||||
SDL_GPUTransferBuffer* downloadBuffer
|
SDL_GPUTransferBuffer* downloadBuffer
|
||||||
);
|
);
|
||||||
|
void WaitForPendingUpload();
|
||||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||||
SDL_GPUTransferBuffer* GetUploadBuffer(size_t size);
|
SDL_GPUTransferBuffer* GetUploadBuffer(size_t size);
|
||||||
|
SDL_GPUTexture* CreateTextureFromSurface(SDL_Surface* surface);
|
||||||
|
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||||
|
SDL3MeshCache UploadMesh(const MeshGroup& meshGroup);
|
||||||
|
|
||||||
DWORD m_width;
|
DWORD m_width;
|
||||||
DWORD m_height;
|
DWORD m_height;
|
||||||
D3DVALUE m_front;
|
D3DVALUE m_front;
|
||||||
D3DVALUE m_back;
|
D3DVALUE m_back;
|
||||||
int m_vertexCount;
|
|
||||||
int m_vertexBufferCount = 0;
|
|
||||||
ViewportUniforms m_uniforms;
|
ViewportUniforms m_uniforms;
|
||||||
FragmentShadingData m_fragmentShadingData;
|
FragmentShadingData m_fragmentShadingData;
|
||||||
D3DDEVICEDESC m_desc;
|
D3DDEVICEDESC m_desc;
|
||||||
D3DRMMATRIX4D m_viewMatrix;
|
D3DRMMATRIX4D m_viewMatrix;
|
||||||
std::vector<SDL3TextureCache> m_textures;
|
std::vector<SDL3TextureCache> m_textures;
|
||||||
|
std::vector<SDL3MeshCache> m_meshs;
|
||||||
SDL_GPUDevice* m_device;
|
SDL_GPUDevice* m_device;
|
||||||
SDL_GPUGraphicsPipeline* m_opaquePipeline;
|
SDL_GPUGraphicsPipeline* m_opaquePipeline;
|
||||||
SDL_GPUGraphicsPipeline* m_transparentPipeline;
|
SDL_GPUGraphicsPipeline* m_transparentPipeline;
|
||||||
@ -96,6 +103,9 @@ class Direct3DRMSDL3GPURenderer : public Direct3DRMRenderer {
|
|||||||
SDL_GPUTransferBuffer* m_downloadBuffer;
|
SDL_GPUTransferBuffer* m_downloadBuffer;
|
||||||
SDL_GPUBuffer* m_vertexBuffer = nullptr;
|
SDL_GPUBuffer* m_vertexBuffer = nullptr;
|
||||||
SDL_GPUSampler* m_sampler;
|
SDL_GPUSampler* m_sampler;
|
||||||
|
SDL_GPUCommandBuffer* m_cmdbuf = nullptr;
|
||||||
|
SDL_GPURenderPass* m_renderPass = nullptr;
|
||||||
|
SDL_GPUFence* m_uploadFence = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
inline static void Direct3DRMSDL3GPU_EnumDevice(LPD3DENUMDEVICESCALLBACK cb, void* ctx)
|
||||||
|
|||||||
@ -16,11 +16,20 @@ struct TextureCache {
|
|||||||
SDL_Surface* cached;
|
SDL_Surface* cached;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct MeshCache {
|
||||||
|
const MeshGroup* meshGroup;
|
||||||
|
int version;
|
||||||
|
bool flat;
|
||||||
|
std::vector<D3DRMVERTEX> vertices;
|
||||||
|
std::vector<DWORD> indices;
|
||||||
|
};
|
||||||
|
|
||||||
class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
||||||
public:
|
public:
|
||||||
Direct3DRMSoftwareRenderer(DWORD width, DWORD height);
|
Direct3DRMSoftwareRenderer(DWORD width, DWORD height);
|
||||||
void PushLights(const SceneLight* vertices, size_t count) override;
|
void PushLights(const SceneLight* vertices, size_t count) override;
|
||||||
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
Uint32 GetTextureId(IDirect3DRMTexture* texture) override;
|
||||||
|
Uint32 GetMeshId(IDirect3DRMMesh* mesh, const MeshGroup* meshGroup) override;
|
||||||
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
void SetProjection(const D3DRMMATRIX4D& projection, D3DVALUE front, D3DVALUE back) override;
|
||||||
DWORD GetWidth() override;
|
DWORD GetWidth() override;
|
||||||
DWORD GetHeight() override;
|
DWORD GetHeight() override;
|
||||||
@ -28,10 +37,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
|||||||
const char* GetName() override;
|
const char* GetName() override;
|
||||||
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
HRESULT BeginFrame(const D3DRMMATRIX4D& viewMatrix) override;
|
||||||
void SubmitDraw(
|
void SubmitDraw(
|
||||||
const D3DRMVERTEX* vertices,
|
DWORD meshId,
|
||||||
const size_t vertexCount,
|
|
||||||
const DWORD* indices,
|
|
||||||
const size_t indexCount,
|
|
||||||
const D3DRMMATRIX4D& worldMatrix,
|
const D3DRMMATRIX4D& worldMatrix,
|
||||||
const Matrix3x3& normalMatrix,
|
const Matrix3x3& normalMatrix,
|
||||||
const Appearance& appearance
|
const Appearance& appearance
|
||||||
@ -51,6 +57,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
|||||||
void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
void BlendPixel(Uint8* pixelAddr, Uint8 r, Uint8 g, Uint8 b, Uint8 a);
|
||||||
SDL_Color ApplyLighting(const D3DVECTOR& position, const D3DVECTOR& normal, const Appearance& appearance);
|
SDL_Color ApplyLighting(const D3DVECTOR& position, const D3DVECTOR& normal, const Appearance& appearance);
|
||||||
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
void AddTextureDestroyCallback(Uint32 id, IDirect3DRMTexture* texture);
|
||||||
|
void AddMeshDestroyCallback(Uint32 id, IDirect3DRMMesh* mesh);
|
||||||
|
|
||||||
DWORD m_width;
|
DWORD m_width;
|
||||||
DWORD m_height;
|
DWORD m_height;
|
||||||
@ -59,6 +66,7 @@ class Direct3DRMSoftwareRenderer : public Direct3DRMRenderer {
|
|||||||
int m_bytesPerPixel;
|
int m_bytesPerPixel;
|
||||||
std::vector<SceneLight> m_lights;
|
std::vector<SceneLight> m_lights;
|
||||||
std::vector<TextureCache> m_textures;
|
std::vector<TextureCache> m_textures;
|
||||||
|
std::vector<MeshCache> m_meshs;
|
||||||
D3DVALUE m_front;
|
D3DVALUE m_front;
|
||||||
D3DVALUE m_back;
|
D3DVALUE m_back;
|
||||||
D3DRMMATRIX4D m_viewMatrix;
|
D3DRMMATRIX4D m_viewMatrix;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user