Add support for using the correct pipeline for each surface
This commit is contained in:
parent
2cda07245c
commit
04493ade52
10 changed files with 247 additions and 118 deletions
|
|
@ -38,6 +38,7 @@
|
|||
#include "hw_cvars.h"
|
||||
#include "hw_skydome.h"
|
||||
#include "flatvertices.h"
|
||||
#include "hw_meshbuilder.h"
|
||||
|
||||
#include "vk_renderdevice.h"
|
||||
#include "vulkan/vk_renderstate.h"
|
||||
|
|
@ -70,6 +71,7 @@ FString JitCaptureStackTrace(int framesToSkip, bool includeNativeFrames, int max
|
|||
EXTERN_CVAR(Int, gl_tonemap)
|
||||
EXTERN_CVAR(Int, screenblocks)
|
||||
EXTERN_CVAR(Bool, cl_capfps)
|
||||
EXTERN_CVAR(Bool, r_skipmats)
|
||||
|
||||
// Physical device info
|
||||
static std::vector<VulkanCompatibleDevice> SupportedDevices;
|
||||
|
|
@ -611,6 +613,120 @@ int VulkanRenderDevice::GetBindlessTextureIndex(FMaterial* material, int clampmo
|
|||
return static_cast<VkMaterial*>(material)->GetBindlessIndex(materialState);
|
||||
}
|
||||
|
||||
int VulkanRenderDevice::GetLevelMeshPipelineID(const MeshApplyData& applyData, const SurfaceUniforms& surfaceUniforms, const FMaterialState& material)
|
||||
{
|
||||
if (levelVertexFormatIndex == -1)
|
||||
{
|
||||
static const std::vector<FVertexBufferAttribute> format =
|
||||
{
|
||||
{ 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FFlatVertex, x) },
|
||||
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) },
|
||||
{ 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FFlatVertex, lu) },
|
||||
{ 1, VATTR_UNIFORM_INDEXES, VFmt_Int, 0 }
|
||||
};
|
||||
levelVertexFormatIndex = GetRenderPassManager()->GetVertexFormat({ sizeof(FFlatVertex), sizeof(int32_t) }, format);
|
||||
}
|
||||
|
||||
VkPipelineKey pipelineKey;
|
||||
pipelineKey.DrawType = DT_Triangles;
|
||||
pipelineKey.VertexFormat = levelVertexFormatIndex;
|
||||
pipelineKey.RenderStyle = applyData.RenderStyle;
|
||||
pipelineKey.DepthTest = true; // mDepthTest;
|
||||
pipelineKey.DepthWrite = true; // mDepthTest && mDepthWrite;
|
||||
pipelineKey.DepthFunc = applyData.DepthFunc;
|
||||
pipelineKey.DepthClamp = false; // mDepthClamp;
|
||||
pipelineKey.DepthBias = false; // !(mBias.mFactor == 0 && mBias.mUnits == 0);
|
||||
pipelineKey.StencilTest = false; // mStencilTest;
|
||||
pipelineKey.StencilPassOp = 0; // mStencilOp;
|
||||
pipelineKey.ColorMask = 15; // mColorMask;
|
||||
pipelineKey.CullMode = 0; // mCullMode;
|
||||
pipelineKey.NumTextureLayers = material.mMaterial ? material.mMaterial->NumLayers() : 0;
|
||||
pipelineKey.NumTextureLayers = max(pipelineKey.NumTextureLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS);// Always force minimum 8 textures as the shader requires it
|
||||
if (applyData.SpecialEffect > EFF_NONE)
|
||||
{
|
||||
pipelineKey.ShaderKey.SpecialEffect = applyData.SpecialEffect;
|
||||
pipelineKey.ShaderKey.EffectState = 0;
|
||||
pipelineKey.ShaderKey.AlphaTest = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int effectState = material.mOverrideShader >= 0 ? material.mOverrideShader : (material.mMaterial ? material.mMaterial->GetShaderIndex() : 0);
|
||||
pipelineKey.ShaderKey.SpecialEffect = EFF_NONE;
|
||||
pipelineKey.ShaderKey.EffectState = applyData.TextureEnabled ? effectState : SHADER_NoTexture;
|
||||
if (r_skipmats && pipelineKey.ShaderKey.EffectState >= 3 && pipelineKey.ShaderKey.EffectState <= 4)
|
||||
pipelineKey.ShaderKey.EffectState = 0;
|
||||
pipelineKey.ShaderKey.AlphaTest = surfaceUniforms.uAlphaThreshold >= 0.f;
|
||||
}
|
||||
|
||||
int tempTM = (material.mMaterial && material.mMaterial->Source()->isHardwareCanvas()) ? TM_OPAQUE : TM_NORMAL;
|
||||
int f = applyData.TextureModeFlags;
|
||||
if (!applyData.BrightmapEnabled) f &= ~(TEXF_Brightmap | TEXF_Glowmap);
|
||||
if (applyData.TextureClamp) f |= TEXF_ClampY;
|
||||
int uTextureMode = (applyData.TextureMode == TM_NORMAL && tempTM == TM_OPAQUE ? TM_OPAQUE : applyData.TextureMode) | f;
|
||||
|
||||
pipelineKey.ShaderKey.TextureMode = uTextureMode & 0xffff;
|
||||
pipelineKey.ShaderKey.ClampY = (uTextureMode & TEXF_ClampY) != 0;
|
||||
pipelineKey.ShaderKey.Brightmap = (uTextureMode & TEXF_Brightmap) != 0;
|
||||
pipelineKey.ShaderKey.Detailmap = (uTextureMode & TEXF_Detailmap) != 0;
|
||||
pipelineKey.ShaderKey.Glowmap = (uTextureMode & TEXF_Glowmap) != 0;
|
||||
|
||||
// The way GZDoom handles state is just plain insanity!
|
||||
int fogset = 0;
|
||||
if (applyData.FogEnabled)
|
||||
{
|
||||
if (applyData.FogEnabled == 2)
|
||||
{
|
||||
fogset = -3; // 2D rendering with 'foggy' overlay.
|
||||
}
|
||||
else if (applyData.FogColor)
|
||||
{
|
||||
fogset = gl_fogmode;
|
||||
}
|
||||
else
|
||||
{
|
||||
fogset = -gl_fogmode;
|
||||
}
|
||||
}
|
||||
pipelineKey.ShaderKey.Simple2D = (fogset == -3);
|
||||
pipelineKey.ShaderKey.FogBeforeLights = (fogset > 0);
|
||||
pipelineKey.ShaderKey.FogAfterLights = (fogset < 0);
|
||||
pipelineKey.ShaderKey.FogRadial = (fogset < -1 || fogset > 1);
|
||||
pipelineKey.ShaderKey.SWLightRadial = (gl_fogmode == 2);
|
||||
pipelineKey.ShaderKey.SWLightBanded = false; // gl_bandedswlight;
|
||||
|
||||
float lightlevel = surfaceUniforms.uLightLevel;
|
||||
if (lightlevel < 0.0)
|
||||
{
|
||||
pipelineKey.ShaderKey.LightMode = 0; // Default
|
||||
}
|
||||
else
|
||||
{
|
||||
/*if (mLightMode == 5)
|
||||
pipelineKey.ShaderKey.LightMode = 3; // Build
|
||||
else if (mLightMode == 16)
|
||||
pipelineKey.ShaderKey.LightMode = 2; // Vanilla
|
||||
else*/
|
||||
pipelineKey.ShaderKey.LightMode = 1; // Software
|
||||
}
|
||||
|
||||
pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1;
|
||||
pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2;
|
||||
|
||||
pipelineKey.ShaderKey.GBufferPass = false;
|
||||
pipelineKey.ShaderKey.UseLevelMesh = true;
|
||||
|
||||
for (unsigned int i = 0, count = levelMeshPipelineKeys.Size(); i < count; i++)
|
||||
{
|
||||
if (levelMeshPipelineKeys[i] == pipelineKey)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
levelMeshPipelineKeys.Push(pipelineKey);
|
||||
return levelMeshPipelineKeys.Size() - 1;
|
||||
}
|
||||
|
||||
void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint)
|
||||
{
|
||||
auto cmdbuffer = GetCommands()->GetDrawCommands();
|
||||
|
|
@ -658,48 +774,11 @@ void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint)
|
|||
cmdbuffer->setStencilReference(VK_STENCIL_FRONT_AND_BACK, 0);
|
||||
cmdbuffer->setDepthBias(0.0f, 0.0f, 0.0f);
|
||||
|
||||
static const std::vector<FVertexBufferAttribute> format =
|
||||
{
|
||||
{ 0, VATTR_VERTEX, VFmt_Float4, (int)myoffsetof(FFlatVertex, x) },
|
||||
{ 0, VATTR_TEXCOORD, VFmt_Float2, (int)myoffsetof(FFlatVertex, u) },
|
||||
{ 0, VATTR_LIGHTMAP, VFmt_Float2, (int)myoffsetof(FFlatVertex, lu) },
|
||||
{ 1, VATTR_UNIFORM_INDEXES, VFmt_Int, 0 }
|
||||
};
|
||||
int vertexFormatIndex = GetRenderPassManager()->GetVertexFormat({ sizeof(FFlatVertex), sizeof(int32_t) }, format);
|
||||
VkBuffer vertexBuffers[2] = { GetRaytrace()->GetVertexBuffer()->buffer, GetRaytrace()->GetUniformIndexBuffer()->buffer };
|
||||
VkDeviceSize vertexBufferOffsets[] = { 0, 0 };
|
||||
cmdbuffer->bindVertexBuffers(0, 2, vertexBuffers, vertexBufferOffsets);
|
||||
cmdbuffer->bindIndexBuffer(GetRaytrace()->GetIndexBuffer()->buffer, 0, VK_INDEX_TYPE_UINT32);
|
||||
|
||||
VkPipelineKey pipelineKey;
|
||||
pipelineKey.DrawType = DT_Triangles;
|
||||
pipelineKey.VertexFormat = vertexFormatIndex;
|
||||
pipelineKey.RenderStyle = DefaultRenderStyle();
|
||||
pipelineKey.DepthTest = true;
|
||||
pipelineKey.DepthWrite = true;
|
||||
pipelineKey.DepthFunc = DF_Less;
|
||||
pipelineKey.DepthClamp = false;
|
||||
pipelineKey.DepthBias = false;
|
||||
pipelineKey.StencilTest = false;
|
||||
pipelineKey.StencilPassOp = 0;
|
||||
pipelineKey.ColorMask = 15;
|
||||
pipelineKey.CullMode = 0;
|
||||
pipelineKey.NumTextureLayers = 0;
|
||||
pipelineKey.NumTextureLayers = max(pipelineKey.NumTextureLayers, SHADER_MIN_REQUIRED_TEXTURE_LAYERS);// Always force minimum 8 textures as the shader requires it
|
||||
pipelineKey.ShaderKey.SpecialEffect = EFF_NONE;
|
||||
pipelineKey.ShaderKey.EffectState = SHADER_Default;
|
||||
pipelineKey.ShaderKey.AlphaTest = false;
|
||||
pipelineKey.ShaderKey.SWLightRadial = true;
|
||||
pipelineKey.ShaderKey.LightMode = 1; // Software
|
||||
pipelineKey.ShaderKey.UseShadowmap = gl_light_shadows == 1;
|
||||
pipelineKey.ShaderKey.UseRaytrace = gl_light_shadows == 2;
|
||||
pipelineKey.ShaderKey.GBufferPass = key.DrawBuffers > 1;
|
||||
pipelineKey.ShaderKey.UseLevelMesh = true;
|
||||
|
||||
VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh);
|
||||
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey));
|
||||
|
||||
auto rsbuffers = GetBufferManager()->GetRSBuffers();
|
||||
memcpy(((char*)rsbuffers->Viewpoint.Data) + rsbuffers->Viewpoint.UploadIndex * rsbuffers->Viewpoint.BlockAlign, &viewpoint, sizeof(HWViewpointUniforms));
|
||||
int viewpointIndex = rsbuffers->Viewpoint.UploadIndex++;
|
||||
|
|
@ -710,21 +789,29 @@ void VulkanRenderDevice::DrawLevelMesh(const HWViewpointUniforms& viewpoint)
|
|||
matrices.TextureMatrix.loadIdentity();
|
||||
rsbuffers->MatrixBuffer->Write(matrices);
|
||||
|
||||
uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign;
|
||||
uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset();
|
||||
uint32_t lightsOffset = 0;
|
||||
uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset };
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets);
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet());
|
||||
auto submesh = GetRaytrace()->GetMesh()->StaticMesh.get();
|
||||
for (LevelSubmeshDrawRange& range : submesh->DrawList)
|
||||
{
|
||||
auto& pipelineKey = levelMeshPipelineKeys[range.PipelineID];
|
||||
VulkanPipelineLayout* layout = GetRenderPassManager()->GetPipelineLayout(pipelineKey.NumTextureLayers, pipelineKey.ShaderKey.UseLevelMesh);
|
||||
cmdbuffer->bindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, passSetup->GetPipeline(pipelineKey));
|
||||
|
||||
PushConstants pushConstants = {};
|
||||
pushConstants.uDataIndex = 0;
|
||||
pushConstants.uLightIndex = -1;
|
||||
pushConstants.uBoneIndexBase = -1;
|
||||
cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants);
|
||||
uint32_t viewpointOffset = viewpointIndex * rsbuffers->Viewpoint.BlockAlign;
|
||||
uint32_t matrixOffset = rsbuffers->MatrixBuffer->Offset();
|
||||
uint32_t lightsOffset = 0;
|
||||
uint32_t offsets[] = { viewpointOffset, matrixOffset, lightsOffset };
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 0, descriptors->GetFixedSet());
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 1, descriptors->GetLevelMeshSet(), 3, offsets);
|
||||
cmdbuffer->bindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, layout, 2, descriptors->GetBindlessSet());
|
||||
|
||||
cmdbuffer->drawIndexed(GetRaytrace()->GetIndexCount(), 1, 0, 0, 0);
|
||||
PushConstants pushConstants = {};
|
||||
pushConstants.uDataIndex = 0;
|
||||
pushConstants.uLightIndex = -1;
|
||||
pushConstants.uBoneIndexBase = -1;
|
||||
cmdbuffer->pushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT, 0, (uint32_t)sizeof(PushConstants), &pushConstants);
|
||||
|
||||
cmdbuffer->drawIndexed(range.Count, 1, range.Start, 0, 0);
|
||||
}
|
||||
|
||||
cmdbuffer->endRenderPass();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue