Fixed a bug with spec maps.

This commit is contained in:
Justin Marshall
2026-05-07 12:26:46 -07:00
parent 1a6bc0c447
commit 469be38dbe
6 changed files with 434 additions and 54 deletions
+313 -22
View File
@@ -158,6 +158,9 @@ using Microsoft::WRL::ComPtr;
#ifndef GL_GLOW_MAP_BINDING_QD3D12
#define GL_GLOW_MAP_BINDING_QD3D12 0x6005
#endif
#ifndef GL_SPECULAR_MAP_BINDING_QD3D12
#define GL_SPECULAR_MAP_BINDING_QD3D12 0x6006
#endif
// Optional material/ray-visibility tags for the DXR path. These are private
// shim enums; they deliberately live next to the normal-map compatibility enums.
@@ -220,6 +223,11 @@ void APIENTRY glTextureGlowMap(GLuint texture, GLboolean isGlowMap);
void APIENTRY glBindGlowMapTexture(GLuint texture);
void APIENTRY glGlowMapTexture(GLuint texture);
void APIENTRY glGlowMapStrengthf(GLfloat strength);
void APIENTRY glTagTextureSpecularMap(GLuint texture, GLboolean isSpecularMap);
void APIENTRY glTextureSpecularMap(GLuint texture, GLboolean isSpecularMap);
void APIENTRY glBindSpecularMapTexture(GLuint texture);
void APIENTRY glSpecularMapTexture(GLuint texture);
void APIENTRY glSpecularMapStrengthf(GLfloat strength);
void APIENTRY glRaytracingMaterialFlagsQD3D12(GLuint flags);
void APIENTRY glRaytracingMaterialFlagQD3D12(GLuint flag, GLboolean enable);
@@ -230,6 +238,7 @@ void glRaytracingLightingSetExternalDenoiser(int enable);
void glRaytracingLightingSetPathTracingOptions(uint32_t samplesPerPixel, uint32_t maxBounces, int enableDenoiser, float denoiseStrength);
void glRaytracingLightingSetVolumetricScattering(glRaytracingLight_t* light, float strength);
void glRaytracingLightingSetEmissiveInput(ID3D12Resource* texture, DXGI_FORMAT format);
void glRaytracingLightingSetSpecularInput(ID3D12Resource* texture, DXGI_FORMAT format);
void glRaytracingSetMeshMaterialFlags(glRaytracingMeshHandle_t meshHandle, uint32_t materialFlags);
void glRaytracingSetMeshGlass(glRaytracingMeshHandle_t meshHandle, int isGlass);
uint32_t glRaytracingGetMeshMaterialFlags(glRaytracingMeshHandle_t meshHandle);
@@ -354,11 +363,14 @@ enum QD3D12RTVSlotGroup
QD3D12_RTV_VELOCITY_RESOLVED = 8,
QD3D12_RTV_EMISSIVE_RESOLVED = 9,
QD3D12_RTV_BACKBUFFER = 10,
QD3D12_RTV_GROUP_COUNT = 11
QD3D12_RTV_SPECULAR_RENDER = 11,
QD3D12_RTV_SPECULAR_RESOLVED = 12,
QD3D12_RTV_GROUP_COUNT = 13
};
static const DXGI_FORMAT QD3D12_SceneColorFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
static const DXGI_FORMAT QD3D12_EmissiveFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
static const DXGI_FORMAT QD3D12_SpecularAlbedoFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
static const DXGI_FORMAT QD3D12_StreamlineOutputFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
static const DXGI_FORMAT QD3D12_VelocityFormat = DXGI_FORMAT_R16G16B16A16_FLOAT;
static const DXGI_FORMAT QD3D12_DepthFormat = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
@@ -488,6 +500,7 @@ struct TextureResource
// from any active texture unit.
bool isNormalMap = false;
bool isGlowMap = false;
bool isSpecularMap = false;
};
static void QD3D12_ShutdownMipWorkers();
@@ -529,6 +542,7 @@ struct DrawConstants
float jitterPixels[2];
float prevJitterPixels[2];
float _motionPad[4];
float materialMapPad[4];
float texComb0RGB[4];
float texComb0Alpha[4];
@@ -562,7 +576,7 @@ struct GLBufferObject
const char* vendor = "Justin Marshall";
const char* renderer = "Quake D3D12 Wrapper";
const char* version = "1.1-quake-d3d12";
const char* extensions = "GL_SGIS_multitexture GL_ARB_multitexture GL_EXT_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_compression GL_EXT_texture_compression_s3tc GL_ARB_vertex_program GL_ARB_fragment_program GL_EXT_texture_cube_map GL_EXT_depth_bounds_test GL_EXT_stencil_two_side GL_ATI_separate_stencil GL_QD3D12_normal_map GL_QD3D12_glow_map GL_QD3D12_glass_material GL_QD3D12_volumetric_light";
const char* extensions = "GL_SGIS_multitexture GL_ARB_multitexture GL_EXT_texture_env_add GL_ARB_texture_env_combine GL_ARB_texture_compression GL_EXT_texture_compression_s3tc GL_ARB_vertex_program GL_ARB_fragment_program GL_EXT_texture_cube_map GL_EXT_depth_bounds_test GL_EXT_stencil_two_side GL_ATI_separate_stencil GL_QD3D12_normal_map GL_QD3D12_glow_map GL_QD3D12_specular_map GL_QD3D12_glass_material GL_QD3D12_volumetric_light";
enum TexEnvModeShader
{
@@ -610,6 +624,9 @@ struct BatchKey
UINT glowMapSrvIndex = 0;
float useGlowMap = 0.0f;
float glowMapStrength = 1.0f;
UINT specularMapSrvIndex = 0;
float useSpecularMap = 0.0f;
float specularMapStrength = 1.0f;
bool useARBPrograms = false;
GLuint arbVertexProgram = 0;
@@ -721,6 +738,9 @@ static bool BatchKeyEquals(const BatchKey& a, const BatchKey& b)
a.glowMapSrvIndex == b.glowMapSrvIndex &&
a.useGlowMap == b.useGlowMap &&
a.glowMapStrength == b.glowMapStrength &&
a.specularMapSrvIndex == b.specularMapSrvIndex &&
a.useSpecularMap == b.useSpecularMap &&
a.specularMapStrength == b.specularMapStrength &&
a.alphaRef == b.alphaRef &&
a.alphaFunc == b.alphaFunc &&
a.useTex0 == b.useTex0 &&
@@ -827,6 +847,9 @@ struct QD3D12Window
std::array<ComPtr<ID3D12Resource>, QD3D12_FrameCount> emissiveBuffers;
D3D12_RESOURCE_STATES emissiveBufferState[QD3D12_FrameCount] = {};
std::array<ComPtr<ID3D12Resource>, QD3D12_FrameCount> specularBuffers;
D3D12_RESOURCE_STATES specularBufferState[QD3D12_FrameCount] = {};
std::array<ComPtr<ID3D12Resource>, QD3D12_FrameCount> sceneColorMsaaBuffers;
D3D12_RESOURCE_STATES sceneColorMsaaState[QD3D12_FrameCount] = {};
@@ -842,6 +865,9 @@ struct QD3D12Window
std::array<ComPtr<ID3D12Resource>, QD3D12_FrameCount> emissiveMsaaBuffers;
D3D12_RESOURCE_STATES emissiveMsaaState[QD3D12_FrameCount] = {};
std::array<ComPtr<ID3D12Resource>, QD3D12_FrameCount> specularMsaaBuffers;
D3D12_RESOURCE_STATES specularMsaaState[QD3D12_FrameCount] = {};
std::array<ComPtr<ID3D12Resource>, QD3D12_FrameCount> backBuffers;
D3D12_RESOURCE_STATES backBufferState[QD3D12_FrameCount] = {};
@@ -879,6 +905,10 @@ struct QD3D12Window
D3D12_CPU_DESCRIPTOR_HANDLE emissiveSrvCpu[QD3D12_FrameCount]{};
D3D12_GPU_DESCRIPTOR_HANDLE emissiveSrvGpu[QD3D12_FrameCount]{};
UINT specularSrvIndex[QD3D12_FrameCount] = { UINT_MAX, UINT_MAX };
D3D12_CPU_DESCRIPTOR_HANDLE specularSrvCpu[QD3D12_FrameCount]{};
D3D12_GPU_DESCRIPTOR_HANDLE specularSrvGpu[QD3D12_FrameCount]{};
UINT slOutputSrvIndex[QD3D12_FrameCount] = { UINT_MAX, UINT_MAX };
D3D12_CPU_DESCRIPTOR_HANDLE slOutputSrvCpu[QD3D12_FrameCount]{};
D3D12_GPU_DESCRIPTOR_HANDLE slOutputSrvGpu[QD3D12_FrameCount]{};
@@ -907,6 +937,10 @@ struct QD3D12Window
D3D12_CPU_DESCRIPTOR_HANDLE emissiveMsaaSrvCpu[QD3D12_FrameCount]{};
D3D12_GPU_DESCRIPTOR_HANDLE emissiveMsaaSrvGpu[QD3D12_FrameCount]{};
UINT specularMsaaSrvIndex[QD3D12_FrameCount] = { UINT_MAX, UINT_MAX };
D3D12_CPU_DESCRIPTOR_HANDLE specularMsaaSrvCpu[QD3D12_FrameCount]{};
D3D12_GPU_DESCRIPTOR_HANDLE specularMsaaSrvGpu[QD3D12_FrameCount]{};
D3D12_VIEWPORT viewport{};
D3D12_RECT scissor{};
@@ -1180,6 +1214,8 @@ struct GLState
float currentNormalMapYSign = 1.0f;
GLuint currentGlowMapTexture = 0;
float currentGlowMapStrength = 1.0f;
GLuint currentSpecularMapTexture = 0;
float currentSpecularMapStrength = 1.0f;
ImmediateVertexBuffer immediateVerts;
GLenum matrixMode = GL_MODELVIEW;
@@ -1770,6 +1806,12 @@ static D3D12_CPU_DESCRIPTOR_HANDLE CurrentEmissiveRTV()
return QD3D12_RtvAt(w, QD3D12_RTV_EMISSIVE_RENDER, w.frameIndex);
}
static D3D12_CPU_DESCRIPTOR_HANDLE CurrentSpecularRTV()
{
QD3D12Window& w = *g_currentWindow;
return QD3D12_RtvAt(w, QD3D12_RTV_SPECULAR_RENDER, w.frameIndex);
}
static D3D12_CPU_DESCRIPTOR_HANDLE CurrentResolvedSceneColorRTV()
{
QD3D12Window& w = *g_currentWindow;
@@ -1800,6 +1842,12 @@ static D3D12_CPU_DESCRIPTOR_HANDLE CurrentResolvedEmissiveRTV()
return QD3D12_RtvAt(w, QD3D12_RTV_EMISSIVE_RESOLVED, w.frameIndex);
}
static D3D12_CPU_DESCRIPTOR_HANDLE CurrentResolvedSpecularRTV()
{
QD3D12Window& w = *g_currentWindow;
return QD3D12_RtvAt(w, QD3D12_RTV_SPECULAR_RESOLVED, w.frameIndex);
}
static D3D12_CPU_DESCRIPTOR_HANDLE CurrentBackBufferRTV()
{
QD3D12Window& w = *g_currentWindow;
@@ -1894,6 +1942,12 @@ static bool QD3D12_IsTextureTaggedGlowMap(GLuint id)
return tex && tex->isGlowMap;
}
static bool QD3D12_IsTextureTaggedSpecularMap(GLuint id)
{
TextureResource* tex = QD3D12_FindTextureResource(id);
return tex && tex->isSpecularMap;
}
static TextureResource* QD3D12_SelectNormalMapTexture(TextureResource* const* allTextures)
{
// Explicit material binding wins. This lets callers bind a normal map even
@@ -1965,6 +2019,45 @@ static TextureResource* QD3D12_SelectGlowMapTexture(TextureResource* const* allT
return nullptr;
}
static TextureResource* QD3D12_SelectSpecularMapTexture(TextureResource* const* allTextures)
{
// Explicit material binding wins. Tagged specular maps can also be discovered
// from any fixed-function texture unit without consuming the diffuse/lightmap slots.
if (g_gl.currentSpecularMapTexture != 0)
{
TextureResource* explicitSpecular = QD3D12_FindTextureResource(g_gl.currentSpecularMapTexture);
if (explicitSpecular)
{
// Avoid common cross-role binding mistakes. A texture tagged only as a
// normal or glow map should not silently become specular albedo.
if ((explicitSpecular->isNormalMap && !explicitSpecular->isSpecularMap) ||
(explicitSpecular->isGlowMap && !explicitSpecular->isSpecularMap))
return nullptr;
return explicitSpecular;
}
}
if (allTextures)
{
for (UINT i = 0; i < QD3D12_MaxTextureUnits; ++i)
{
TextureResource* tex = allTextures[i];
if (tex && tex != &g_gl.whiteTexture && tex->isSpecularMap)
return tex;
}
}
for (UINT i = 0; i < QD3D12_MaxTextureUnits; ++i)
{
TextureResource* tex = QD3D12_FindTextureResource(g_gl.boundTexture[i]);
if (tex && tex->isSpecularMap)
return tex;
}
return nullptr;
}
static const uint8_t* QD3D12_ResolveArrayPointer(const void* ptr)
{
if (g_gl.boundArrayBuffer != 0)
@@ -2109,6 +2202,7 @@ cbuffer DrawCB : register(b0)
float2 gJitterPixels;
float2 gPrevJitterPixels;
float4 gMotionPad;
float4 gMaterialMapPad;
float4 gTexComb0RGB;
float4 gTexComb0Alpha;
@@ -2126,15 +2220,19 @@ cbuffer DrawCB : register(b0)
#define gParallaxScale 0.0
#define gUseGlowMap gMotionPad.w
#define gGlowMapStrength gMotionPad.w
#define gUseSpecularMap gMaterialMapPad.x
#define gSpecularMapStrength gMaterialMapPad.y
Texture2D gTex0 : register(t0);
Texture2D gTex1 : register(t1);
Texture2D gNormalMap : register(t2);
Texture2D gGlowMap : register(t3);
Texture2D gSpecularMap : register(t4);
SamplerState gSamp0 : register(s0);
SamplerState gSamp1 : register(s1);
SamplerState gSamp2 : register(s2);
SamplerState gSamp3 : register(s3);
SamplerState gSamp4 : register(s4);
struct VSIn
{
@@ -2171,6 +2269,7 @@ struct PSOut
float4 position : SV_Target2;
float4 velocity : SV_Target3;
float4 emissive : SV_Target4;
float4 specular : SV_Target5;
};
float4 QD3D12_GetTexEnvSource(float source, float4 texel, float4 primary, float4 previous, float4 constantColor)
@@ -2515,6 +2614,26 @@ float4 BuildGlowEmission(VSOut i)
return QD3D12_SampleGlow(i);
}
float4 BuildSpecularAlbedo(VSOut i)
{
if (gUseSpecularMap <= 0.0)
return float4(0.0, 0.0, 0.0, 0.0);
float4 spec = gSpecularMap.Sample(gSamp4, QD3D12_BuildMaterialUV0(i));
float strength = max(gSpecularMapStrength, 0.0);
// RGB-only legacy spec maps are uploaded with forced opaque alpha. For real
// RGBA spec maps, alpha is treated as an artist mask over RGB. The alpha we
// write to the G-buffer is not the brightness mask; it is a presence bit so
// the DXR pass can distinguish "no spec map bound" from an intentional
// black spec-map texel.
bool alphaLooksForcedOpaque = (spec.a >= 0.999);
float alphaMask = alphaLooksForcedOpaque ? 1.0 : saturate(spec.a);
float3 specRgb = saturate(spec.rgb) * alphaMask * strength;
return float4(specRgb, 1.0);
}
float2 ClipToUv(float4 clipPos)
{
float2 ndc = clipPos.xy / max(abs(clipPos.w), 1e-6);
@@ -2572,6 +2691,7 @@ PSOut PSMain(VSOut i)
o.position = float4(i.worldPos, i.attr.x);
o.velocity = BuildVelocity(i);
o.emissive = BuildGlowEmission(i);
o.specular = BuildSpecularAlbedo(i);
return o;
}
@@ -2584,6 +2704,7 @@ PSOut PSMainAlphaTest(VSOut i)
o.position = float4(i.worldPos, i.attr.x);
o.velocity = BuildVelocity(i);
o.emissive = BuildGlowEmission(i);
o.specular = BuildSpecularAlbedo(i);
return o;
}
@@ -2595,6 +2716,7 @@ PSOut PSMainUntextured(VSOut i)
o.position = float4(i.worldPos, i.attr.x);
o.velocity = BuildVelocity(i);
o.emissive = float4(0.0, 0.0, 0.0, 0.0);
o.specular = BuildSpecularAlbedo(i);
return o;
}
@@ -2626,6 +2748,7 @@ Texture2DMS<float4> gNormalMS : register(t2);
Texture2DMS<float4> gPositionMS : register(t3);
Texture2DMS<float4> gVelocityMS : register(t4);
Texture2DMS<float4> gEmissiveMS : register(t5);
Texture2DMS<float4> gSpecularMS : register(t6);
SamplerState gSamp0 : register(s0);
struct VSOut
@@ -2765,6 +2888,7 @@ struct PSGBufferPointResolveOut
float4 position : SV_Target1;
float4 velocity : SV_Target2;
float4 emissive : SV_Target3;
float4 specular : SV_Target4;
};
PSGBufferPointResolveOut PSGBufferPointResolveMS(VSOut i)
@@ -2788,6 +2912,7 @@ PSGBufferPointResolveOut PSGBufferPointResolveMS(VSOut i)
o.position = gPositionMS.Load(int2(srcPixel), sampleIndex);
o.velocity = gVelocityMS.Load(int2(srcPixel), sampleIndex);
o.emissive = gEmissiveMS.Load(int2(srcPixel), sampleIndex);
o.specular = gSpecularMS.Load(int2(srcPixel), sampleIndex);
return o;
}
@@ -3219,6 +3344,19 @@ static BatchKey BuildCurrentBatchKey(GLenum originalMode, const TextureResource*
}
key.glowMapStrength = g_gl.currentGlowMapStrength;
TextureResource* specularMap = QD3D12_SelectSpecularMapTexture(allTextures);
if (specularMap && specularMap->texture && specularMap->srvIndex != UINT_MAX)
{
key.specularMapSrvIndex = specularMap->srvIndex;
key.useSpecularMap = 1.0f;
}
else
{
key.specularMapSrvIndex = g_gl.whiteTexture.srvIndex;
key.useSpecularMap = 0.0f;
}
key.specularMapStrength = g_gl.currentSpecularMapStrength;
key.useARBPrograms = QD3D12ARB_IsActive();
if (key.useARBPrograms)
{
@@ -4546,7 +4684,7 @@ static void QD3D12_RunUpscalerOrBlit(QD3D12Window& w)
sl::Resource mvec = { sl::ResourceType::eTex2d, w.velocityBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::Resource specularMvec = { sl::ResourceType::eTex2d, w.velocityBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::Resource diffuseAlbedo = { sl::ResourceType::eTex2d, w.sceneColorBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::Resource specularAlbedo = { sl::ResourceType::eTex2d, w.sceneColorBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::Resource specularAlbedo = { sl::ResourceType::eTex2d, w.specularBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::Resource normalRoughness = { sl::ResourceType::eTex2d, w.normalBuffers[w.frameIndex].Get(), nullptr, nullptr, uint32_t(D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE) };
sl::ResourceTag tags[] =
@@ -4795,6 +4933,7 @@ static bool QD3D12_CanUseGBufferSampleCount(UINT sampleCount)
// QD3D12_PointResolveMsaaGBufferToSingleSample() point-loads one sample.
QD3D12_FormatSupportsSampleCount(DXGI_FORMAT_R16G16B16A16_FLOAT, sampleCount) &&
QD3D12_FormatSupportsSampleCount(QD3D12_VelocityFormat, sampleCount) &&
QD3D12_FormatSupportsSampleCount(QD3D12_SpecularAlbedoFormat, sampleCount) &&
QD3D12_FormatSupportsSampleCount(QD3D12_DepthDsvFormat, sampleCount);
}
@@ -4938,6 +5077,7 @@ static void QD3D12_CreateRTVsForWindow(QD3D12Window& w)
const float normalClear[4] = { 0.0f, 0.0f, 1.0f, 0.5f };
const float positionClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float velocityClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float specularClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const bool useMsaa = QD3D12_GBufferMsaaEnabled();
const UINT msaaSamples = QD3D12_GBufferSampleCount();
@@ -5073,6 +5213,25 @@ static void QD3D12_CreateRTVsForWindow(QD3D12Window& w)
}
}
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
{
if (useMsaa)
{
CreateTexture2D(w.specularMsaaBuffers[i], w.specularMsaaState[i], QD3D12_SpecularAlbedoFormat, specularClear, true,
w.renderWidth, w.renderHeight, msaaSamples, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET,
QD3D12_RtvAt(w, QD3D12_RTV_SPECULAR_RENDER, i), true);
CreateTexture2D(w.specularBuffers[i], w.specularBufferState[i], QD3D12_SpecularAlbedoFormat, specularClear, false,
w.renderWidth, w.renderHeight, 1, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE,
QD3D12_RtvAt(w, QD3D12_RTV_SPECULAR_RESOLVED, i), true);
}
else
{
CreateTexture2D(w.specularBuffers[i], w.specularBufferState[i], QD3D12_SpecularAlbedoFormat, specularClear, true,
w.renderWidth, w.renderHeight, 1, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_RESOURCE_STATE_RENDER_TARGET,
QD3D12_RtvAt(w, QD3D12_RTV_SPECULAR_RENDER, i), true);
}
}
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
{
D3D12_CPU_DESCRIPTOR_HANDLE backBufferRtv = QD3D12_RtvAt(w, QD3D12_RTV_BACKBUFFER, i);
@@ -5165,6 +5324,9 @@ static void QD3D12_CreateRTVsForWindow(QD3D12Window& w)
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
CreateTextureSrv(w.emissiveBuffers[i].Get(), QD3D12_EmissiveFormat, w.emissiveSrvIndex[i], w.emissiveSrvCpu[i], w.emissiveSrvGpu[i]);
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
CreateTextureSrv(w.specularBuffers[i].Get(), QD3D12_SpecularAlbedoFormat, w.specularSrvIndex[i], w.specularSrvCpu[i], w.specularSrvGpu[i]);
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
CreateTextureSrv(w.slOutputBuffers[i].Get(), QD3D12_StreamlineOutputFormat, w.slOutputSrvIndex[i], w.slOutputSrvCpu[i], w.slOutputSrvGpu[i]);
@@ -5181,6 +5343,9 @@ static void QD3D12_CreateRTVsForWindow(QD3D12Window& w)
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
CreateTextureMsaaSrv(w.emissiveMsaaBuffers[i].Get(), QD3D12_EmissiveFormat, w.emissiveMsaaSrvIndex[i], w.emissiveMsaaSrvCpu[i], w.emissiveMsaaSrvGpu[i]);
for (UINT i = 0; i < QD3D12_FrameCount; ++i)
CreateTextureMsaaSrv(w.specularMsaaBuffers[i].Get(), QD3D12_SpecularAlbedoFormat, w.specularMsaaSrvIndex[i], w.specularMsaaSrvCpu[i], w.specularMsaaSrvGpu[i]);
}
}
@@ -5502,7 +5667,7 @@ static ComPtr<ID3DBlob> CompileShaderVariant(const char* entry, const char* targ
static void QD3D12_CreatePostRootSignature()
{
D3D12_DESCRIPTOR_RANGE ranges[6]{};
D3D12_DESCRIPTOR_RANGE ranges[7]{};
for (UINT i = 0; i < _countof(ranges); ++i)
{
ranges[i].RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
@@ -5512,7 +5677,7 @@ static void QD3D12_CreatePostRootSignature()
ranges[i].OffsetInDescriptorsFromTableStart = 0;
}
D3D12_ROOT_PARAMETER params[6]{};
D3D12_ROOT_PARAMETER params[7]{};
for (UINT i = 0; i < _countof(params); ++i)
{
params[i].ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
@@ -5669,7 +5834,7 @@ static D3D12_GRAPHICS_PIPELINE_STATE_DESC BuildPSODesc(
d.PrimitiveTopologyType = topoType;
d.NumRenderTargets = nativeColorOnly ? 1u : 5u;
d.NumRenderTargets = nativeColorOnly ? 1u : 6u;
d.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
if (!nativeColorOnly)
{
@@ -5677,6 +5842,7 @@ static D3D12_GRAPHICS_PIPELINE_STATE_DESC BuildPSODesc(
d.RTVFormats[2] = DXGI_FORMAT_R16G16B16A16_FLOAT;
d.RTVFormats[3] = QD3D12_VelocityFormat;
d.RTVFormats[4] = QD3D12_EmissiveFormat;
d.RTVFormats[5] = QD3D12_SpecularAlbedoFormat;
}
d.DSVFormat = QD3D12_DepthDsvFormat;
@@ -5695,12 +5861,13 @@ static D3D12_GRAPHICS_PIPELINE_STATE_DESC BuildPSODesc(
d.BlendState.RenderTarget[2].RenderTargetWriteMask = key.colorWriteMask ? D3D12_COLOR_WRITE_ENABLE_ALL : 0;
d.BlendState.RenderTarget[3].RenderTargetWriteMask = key.colorWriteMask ? D3D12_COLOR_WRITE_ENABLE_ALL : 0;
d.BlendState.RenderTarget[4].RenderTargetWriteMask = key.colorWriteMask ? D3D12_COLOR_WRITE_ENABLE_ALL : 0;
d.BlendState.RenderTarget[5].RenderTargetWriteMask = key.colorWriteMask ? D3D12_COLOR_WRITE_ENABLE_ALL : 0;
}
d.BlendState.AlphaToCoverageEnable = FALSE;
d.BlendState.IndependentBlendEnable = nativeColorOnly ? FALSE : TRUE;
for (int i = 0; i < (nativeColorOnly ? 1 : 5); ++i)
for (int i = 0; i < (nativeColorOnly ? 1 : 6); ++i)
{
auto& rt = d.BlendState.RenderTarget[i];
rt.BlendEnable = FALSE;
@@ -5808,17 +5975,18 @@ static void QD3D12_CreatePSOs()
gbufferResolveDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
gbufferResolveDesc.SampleDesc.Count = 1;
gbufferResolveDesc.SampleMask = UINT_MAX;
gbufferResolveDesc.NumRenderTargets = 4;
gbufferResolveDesc.NumRenderTargets = 5;
gbufferResolveDesc.RTVFormats[0] = DXGI_FORMAT_R16G16B16A16_FLOAT;
gbufferResolveDesc.RTVFormats[1] = DXGI_FORMAT_R16G16B16A16_FLOAT;
gbufferResolveDesc.RTVFormats[2] = QD3D12_VelocityFormat;
gbufferResolveDesc.RTVFormats[3] = QD3D12_EmissiveFormat;
gbufferResolveDesc.RTVFormats[4] = QD3D12_SpecularAlbedoFormat;
gbufferResolveDesc.RasterizerState.FillMode = D3D12_FILL_MODE_SOLID;
gbufferResolveDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
gbufferResolveDesc.RasterizerState.DepthClipEnable = TRUE;
gbufferResolveDesc.BlendState.AlphaToCoverageEnable = FALSE;
gbufferResolveDesc.BlendState.IndependentBlendEnable = FALSE;
for (UINT rt = 0; rt < 4; ++rt)
for (UINT rt = 0; rt < 5; ++rt)
{
gbufferResolveDesc.BlendState.RenderTarget[rt].BlendEnable = FALSE;
gbufferResolveDesc.BlendState.RenderTarget[rt].LogicOpEnable = FALSE;
@@ -5937,7 +6105,7 @@ static D3D12_GRAPHICS_PIPELINE_STATE_DESC BuildARBPSODesc(
d.InputLayout.NumElements = _countof(kGLVertexInputLayoutARB);
d.PrimitiveTopologyType = topoType;
d.NumRenderTargets = nativeColorOnly ? 1u : 5u;
d.NumRenderTargets = nativeColorOnly ? 1u : 6u;
d.RTVFormats[0] = DXGI_FORMAT_R8G8B8A8_UNORM;
if (!nativeColorOnly)
{
@@ -5945,6 +6113,7 @@ static D3D12_GRAPHICS_PIPELINE_STATE_DESC BuildARBPSODesc(
d.RTVFormats[2] = DXGI_FORMAT_R16G16B16A16_FLOAT;
d.RTVFormats[3] = QD3D12_VelocityFormat;
d.RTVFormats[4] = QD3D12_EmissiveFormat;
d.RTVFormats[5] = QD3D12_SpecularAlbedoFormat;
}
d.DSVFormat = QD3D12_DepthDsvFormat;
@@ -5959,7 +6128,7 @@ static D3D12_GRAPHICS_PIPELINE_STATE_DESC BuildARBPSODesc(
d.BlendState.AlphaToCoverageEnable = FALSE;
d.BlendState.IndependentBlendEnable = nativeColorOnly ? FALSE : TRUE;
for (int i = 0; i < (nativeColorOnly ? 1 : 5); ++i)
for (int i = 0; i < (nativeColorOnly ? 1 : 6); ++i)
{
auto& rt = d.BlendState.RenderTarget[i];
rt.BlendEnable = FALSE;
@@ -6334,10 +6503,12 @@ void QD3D12_BeginFrame()
const float positionClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float velocityClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float emissiveClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float specularClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
g_gl.cmdList->ClearRenderTargetView(CurrentNormalRTV(), normalClear, 0, nullptr);
g_gl.cmdList->ClearRenderTargetView(CurrentPositionRTV(), positionClear, 0, nullptr);
g_gl.cmdList->ClearRenderTargetView(CurrentVelocityRTV(), velocityClear, 0, nullptr);
g_gl.cmdList->ClearRenderTargetView(CurrentEmissiveRTV(), emissiveClear, 0, nullptr);
g_gl.cmdList->ClearRenderTargetView(CurrentSpecularRTV(), specularClear, 0, nullptr);
g_gl.frameOpen = true;
g_gl.frameOwner = &w;
@@ -6372,6 +6543,7 @@ void QD3D12_EndFrame()
QD3D12_TransitionResource(g_gl.cmdList.Get(), w.normalBuffers[w.frameIndex].Get(), w.normalBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(g_gl.cmdList.Get(), w.positionBuffers[w.frameIndex].Get(), w.positionBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(g_gl.cmdList.Get(), w.velocityBuffers[w.frameIndex].Get(), w.velocityBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(g_gl.cmdList.Get(), w.specularBuffers[w.frameIndex].Get(), w.specularBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(g_gl.cmdList.Get(), w.depthBuffer.Get(), w.depthState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(g_gl.cmdList.Get(), w.backBuffers[w.frameIndex].Get(), w.backBufferState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
@@ -7862,8 +8034,12 @@ static void FlushImmediate(GLenum mode, const GLVertex* src, size_t n)
const bool explicitGlowUnit = (!arbProgramsActive) &&
(g_gl.currentGlowMapTexture != 0) &&
(g_gl.boundTexture[unit] == g_gl.currentGlowMapTexture);
const bool taggedSpecularUnit = (!arbProgramsActive) && QD3D12_IsTextureTaggedSpecularMap(g_gl.boundTexture[unit]);
const bool explicitSpecularUnit = (!arbProgramsActive) &&
(g_gl.currentSpecularMapTexture != 0) &&
(g_gl.boundTexture[unit] == g_gl.currentSpecularMapTexture);
const bool wantsUnit = arbUnit || fixedColorUnit || taggedNormalUnit || explicitNormalUnit || taggedGlowUnit || explicitGlowUnit;
const bool wantsUnit = arbUnit || fixedColorUnit || taggedNormalUnit || explicitNormalUnit || taggedGlowUnit || explicitGlowUnit || taggedSpecularUnit || explicitSpecularUnit;
if (!wantsUnit)
continue;
@@ -7896,6 +8072,13 @@ static void FlushImmediate(GLenum mode, const GLVertex* src, size_t n)
UploadTexture(*glowMapTex);
}
TextureResource* specularMapTex = QD3D12_SelectSpecularMapTexture(boundTextures);
if (specularMapTex && specularMapTex != &g_gl.whiteTexture && !specularMapTex->gpuValid)
{
EnsureTextureResource(*specularMapTex);
UploadTexture(*specularMapTex);
}
TextureResource* tex0 = boundTextures[0];
TextureResource* tex1 = boundTextures[1];
@@ -8202,10 +8385,12 @@ static void QD3D12_FlushQueuedBatches()
D3D12_GPU_DESCRIPTOR_HANDLE lastTex1{};
D3D12_GPU_DESCRIPTOR_HANDLE lastNormalMap{};
D3D12_GPU_DESCRIPTOR_HANDLE lastGlowMap{};
D3D12_GPU_DESCRIPTOR_HANDLE lastSpecularMap{};
bool haveLastTex0 = false;
bool haveLastTex1 = false;
bool haveLastNormalMap = false;
bool haveLastGlowMap = false;
bool haveLastSpecularMap = false;
D3D12_PRIMITIVE_TOPOLOGY lastTopo = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
for (size_t i = 0; i < g_gl.queuedBatches.size(); ++i)
@@ -8232,6 +8417,7 @@ static void QD3D12_FlushQueuedBatches()
haveLastTex1 = false;
haveLastNormalMap = false;
haveLastGlowMap = false;
haveLastSpecularMap = false;
lastTopo = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
}
@@ -8300,6 +8486,10 @@ static void QD3D12_FlushQueuedBatches()
dc->_motionPad[1] = batch.key.normalMapStrength;
dc->_motionPad[2] = batch.key.normalMapYSign;
dc->_motionPad[3] = (batch.key.useGlowMap > 0.5f) ? batch.key.glowMapStrength : 0.0f;
dc->materialMapPad[0] = batch.key.useSpecularMap;
dc->materialMapPad[1] = batch.key.specularMapStrength;
dc->materialMapPad[2] = 0.0f;
dc->materialMapPad[3] = 0.0f;
if (batch.key.useARBPrograms)
{
@@ -8356,6 +8546,7 @@ static void QD3D12_FlushQueuedBatches()
haveLastTex1 = false;
haveLastNormalMap = false;
haveLastGlowMap = false;
haveLastSpecularMap = false;
}
else
{
@@ -8404,6 +8595,18 @@ static void QD3D12_FlushQueuedBatches()
lastGlowMap = glowMapGpu;
haveLastGlowMap = true;
}
UINT specularSrvIndex = batch.key.specularMapSrvIndex;
if (specularSrvIndex == UINT_MAX)
specularSrvIndex = g_gl.whiteTexture.srvIndex;
D3D12_GPU_DESCRIPTOR_HANDLE specularMapGpu = QD3D12_SrvGpu(specularSrvIndex);
if (!haveLastSpecularMap || specularMapGpu.ptr != lastSpecularMap.ptr)
{
g_gl.cmdList->SetGraphicsRootDescriptorTable(5, specularMapGpu);
lastSpecularMap = specularMapGpu;
haveLastSpecularMap = true;
}
}
g_gl.cmdList->SetGraphicsRootConstantBufferView(0, cbAlloc.gpu);
@@ -8535,12 +8738,14 @@ void APIENTRY glClear(GLbitfield mask)
const float positionClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float velocityClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float emissiveClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
const float specularClear[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
g_gl.cmdList->ClearRenderTargetView(CurrentRTV(), cc, 1, &clearRect);
g_gl.cmdList->ClearRenderTargetView(CurrentNormalRTV(), normalClear, 1, &clearRect);
g_gl.cmdList->ClearRenderTargetView(CurrentPositionRTV(), positionClear, 1, &clearRect);
g_gl.cmdList->ClearRenderTargetView(CurrentVelocityRTV(), velocityClear, 1, &clearRect);
g_gl.cmdList->ClearRenderTargetView(CurrentEmissiveRTV(), emissiveClear, 1, &clearRect);
g_gl.cmdList->ClearRenderTargetView(CurrentSpecularRTV(), specularClear, 1, &clearRect);
}
}
@@ -8890,6 +9095,9 @@ void APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
if (g_gl.currentGlowMapTexture == deadId)
g_gl.currentGlowMapTexture = 0;
if (g_gl.currentSpecularMapTexture == deadId)
g_gl.currentSpecularMapTexture = 0;
auto it = g_gl.textures.find(deadId);
if (it != g_gl.textures.end())
{
@@ -8996,6 +9204,49 @@ void APIENTRY glGlowMapStrengthf(GLfloat strength)
g_gl.currentGlowMapStrength = (strength < 0.0f) ? 0.0f : strength;
}
void APIENTRY glTagTextureSpecularMap(GLuint texture, GLboolean isSpecularMap)
{
if (texture == 0)
{
g_gl.lastError = GL_INVALID_VALUE;
return;
}
TextureResource& tex = QD3D12_EnsureTextureName(texture);
tex.isSpecularMap = (isSpecularMap != GL_FALSE);
}
void APIENTRY glTextureSpecularMap(GLuint texture, GLboolean isSpecularMap)
{
glTagTextureSpecularMap(texture, isSpecularMap);
}
void APIENTRY glBindSpecularMapTexture(GLuint texture)
{
if (texture != 0)
{
TextureResource& tex = QD3D12_EnsureTextureName(texture);
if ((tex.isNormalMap && !tex.isSpecularMap) || (tex.isGlowMap && !tex.isSpecularMap))
{
QD3D12_Log("glBindSpecularMapTexture(%u) ignored: texture is tagged as a different material map role.", texture);
g_gl.currentSpecularMapTexture = 0;
return;
}
}
g_gl.currentSpecularMapTexture = texture;
}
void APIENTRY glSpecularMapTexture(GLuint texture)
{
glBindSpecularMapTexture(texture);
}
void APIENTRY glSpecularMapStrengthf(GLfloat strength)
{
g_gl.currentSpecularMapStrength = (strength < 0.0f) ? 0.0f : strength;
}
void APIENTRY glRaytracingMaterialFlagsQD3D12(GLuint flags)
{
g_gl.currentRayMaterialFlags = QD3D12_ClampRayMaterialFlags((uint32_t)flags);
@@ -9136,6 +9387,10 @@ void APIENTRY glGetIntegerv(GLenum pname, GLint* params)
*params = (GLint)g_gl.currentGlowMapTexture;
break;
case GL_SPECULAR_MAP_BINDING_QD3D12:
*params = (GLint)g_gl.currentSpecularMapTexture;
break;
case GL_QD3D12_MATERIAL_FLAGS:
*params = (GLint)QD3D12_CurrentRayMaterialFlags();
break;
@@ -10138,10 +10393,14 @@ void QD3D12_ReleaseWindowSizeResources(QD3D12Window& w)
w.normalBuffers[i].Reset();
w.positionBuffers[i].Reset();
w.velocityBuffers[i].Reset();
w.emissiveBuffers[i].Reset();
w.specularBuffers[i].Reset();
w.sceneColorMsaaBuffers[i].Reset();
w.normalMsaaBuffers[i].Reset();
w.positionMsaaBuffers[i].Reset();
w.velocityMsaaBuffers[i].Reset();
w.emissiveMsaaBuffers[i].Reset();
w.specularMsaaBuffers[i].Reset();
w.slOutputBuffers[i].Reset();
w.sceneColorState[i] = D3D12_RESOURCE_STATE_COMMON;
@@ -10149,10 +10408,14 @@ void QD3D12_ReleaseWindowSizeResources(QD3D12Window& w)
w.normalBufferState[i] = D3D12_RESOURCE_STATE_COMMON;
w.positionBufferState[i] = D3D12_RESOURCE_STATE_COMMON;
w.velocityBufferState[i] = D3D12_RESOURCE_STATE_COMMON;
w.emissiveBufferState[i] = D3D12_RESOURCE_STATE_COMMON;
w.specularBufferState[i] = D3D12_RESOURCE_STATE_COMMON;
w.sceneColorMsaaState[i] = D3D12_RESOURCE_STATE_COMMON;
w.normalMsaaState[i] = D3D12_RESOURCE_STATE_COMMON;
w.positionMsaaState[i] = D3D12_RESOURCE_STATE_COMMON;
w.velocityMsaaState[i] = D3D12_RESOURCE_STATE_COMMON;
w.emissiveMsaaState[i] = D3D12_RESOURCE_STATE_COMMON;
w.specularMsaaState[i] = D3D12_RESOURCE_STATE_COMMON;
w.slOutputState[i] = D3D12_RESOURCE_STATE_COMMON;
}
@@ -11700,6 +11963,11 @@ PROC WINAPI qd3d12_wglGetProcAddress(LPCSTR name) {
{ "glBindGlowMapTexture", (PROC)glBindGlowMapTexture },
{ "glGlowMapTexture", (PROC)glGlowMapTexture },
{ "glGlowMapStrengthf", (PROC)glGlowMapStrengthf },
{ "glTagTextureSpecularMap", (PROC)glTagTextureSpecularMap },
{ "glTextureSpecularMap", (PROC)glTextureSpecularMap },
{ "glBindSpecularMapTexture", (PROC)glBindSpecularMapTexture },
{ "glSpecularMapTexture", (PROC)glSpecularMapTexture },
{ "glSpecularMapStrengthf", (PROC)glSpecularMapStrengthf },
{ "glGlassMaterialQD3D12", (PROC)glGlassMaterialQD3D12 },
{ "glMaterialGlassQD3D12", (PROC)glMaterialGlassQD3D12 },
{ "glRaytracingMaterialFlagsQD3D12", (PROC)glRaytracingMaterialFlagsQD3D12 },
@@ -11959,8 +12227,8 @@ static void QD3D12_PointResolveMsaaGBufferToSingleSample(QD3D12Window& w)
const UINT frame = w.frameIndex;
if (!w.depthMsaaBuffer ||
!w.normalMsaaBuffers[frame] || !w.positionMsaaBuffers[frame] || !w.velocityMsaaBuffers[frame] || !w.emissiveMsaaBuffers[frame] ||
!w.normalBuffers[frame] || !w.positionBuffers[frame] || !w.velocityBuffers[frame] || !w.emissiveBuffers[frame])
!w.normalMsaaBuffers[frame] || !w.positionMsaaBuffers[frame] || !w.velocityMsaaBuffers[frame] || !w.emissiveMsaaBuffers[frame] || !w.specularMsaaBuffers[frame] ||
!w.normalBuffers[frame] || !w.positionBuffers[frame] || !w.velocityBuffers[frame] || !w.emissiveBuffers[frame] || !w.specularBuffers[frame])
{
return;
}
@@ -11970,18 +12238,21 @@ static void QD3D12_PointResolveMsaaGBufferToSingleSample(QD3D12Window& w)
QD3D12_TransitionResource(cl, w.positionMsaaBuffers[frame].Get(), w.positionMsaaState[frame], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(cl, w.velocityMsaaBuffers[frame].Get(), w.velocityMsaaState[frame], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(cl, w.emissiveMsaaBuffers[frame].Get(), w.emissiveMsaaState[frame], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(cl, w.specularMsaaBuffers[frame].Get(), w.specularMsaaState[frame], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(cl, w.normalBuffers[frame].Get(), w.normalBufferState[frame], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.positionBuffers[frame].Get(), w.positionBufferState[frame], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.velocityBuffers[frame].Get(), w.velocityBufferState[frame], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.emissiveBuffers[frame].Get(), w.emissiveBufferState[frame], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.specularBuffers[frame].Get(), w.specularBufferState[frame], D3D12_RESOURCE_STATE_RENDER_TARGET);
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[4] =
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[5] =
{
CurrentResolvedNormalRTV(),
CurrentResolvedPositionRTV(),
CurrentResolvedVelocityRTV(),
CurrentResolvedEmissiveRTV()
CurrentResolvedEmissiveRTV(),
CurrentResolvedSpecularRTV()
};
D3D12_VIEWPORT viewport{};
@@ -12002,18 +12273,19 @@ static void QD3D12_PointResolveMsaaGBufferToSingleSample(QD3D12Window& w)
cl->SetDescriptorHeaps(_countof(heaps), heaps);
cl->SetGraphicsRootSignature(g_gl.postRootSig.Get());
cl->SetPipelineState(g_gl.postGBufferPointResolveMsaaPSO.Get());
cl->OMSetRenderTargets(4, rtvs, FALSE, nullptr);
cl->OMSetRenderTargets(5, rtvs, FALSE, nullptr);
cl->RSSetViewports(1, &viewport);
cl->RSSetScissorRects(1, &scissor);
cl->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// t1..t5: depth + discontinuous G-buffer attributes. The shader uses
// t1..t6: depth + discontinuous G-buffer attributes. The shader uses
// Texture2DMS.Load(), selects a single depth-nearest sample, and never averages.
cl->SetGraphicsRootDescriptorTable(1, w.depthMsaaSrvGpu);
cl->SetGraphicsRootDescriptorTable(2, w.normalMsaaSrvGpu[frame]);
cl->SetGraphicsRootDescriptorTable(3, w.positionMsaaSrvGpu[frame]);
cl->SetGraphicsRootDescriptorTable(4, w.velocityMsaaSrvGpu[frame]);
cl->SetGraphicsRootDescriptorTable(5, w.emissiveMsaaSrvGpu[frame]);
cl->SetGraphicsRootDescriptorTable(6, w.specularMsaaSrvGpu[frame]);
cl->DrawInstanced(3, 1, 0, 0);
}
@@ -12090,6 +12362,7 @@ static void QD3D12_BindLowResSceneTargets(QD3D12Window& w)
QD3D12_TransitionResource(cl, w.positionMsaaBuffers[w.frameIndex].Get(), w.positionMsaaState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.velocityMsaaBuffers[w.frameIndex].Get(), w.velocityMsaaState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.emissiveMsaaBuffers[w.frameIndex].Get(), w.emissiveMsaaState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.specularMsaaBuffers[w.frameIndex].Get(), w.specularMsaaState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.depthMsaaBuffer.Get(), w.depthMsaaState, D3D12_RESOURCE_STATE_DEPTH_WRITE);
}
else
@@ -12099,19 +12372,21 @@ static void QD3D12_BindLowResSceneTargets(QD3D12Window& w)
QD3D12_TransitionResource(cl, w.positionBuffers[w.frameIndex].Get(), w.positionBufferState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.velocityBuffers[w.frameIndex].Get(), w.velocityBufferState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.emissiveBuffers[w.frameIndex].Get(), w.emissiveBufferState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.specularBuffers[w.frameIndex].Get(), w.specularBufferState[w.frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, w.depthBuffer.Get(), w.depthState, D3D12_RESOURCE_STATE_DEPTH_WRITE);
}
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[5] =
D3D12_CPU_DESCRIPTOR_HANDLE rtvs[6] =
{
CurrentRTV(),
CurrentNormalRTV(),
CurrentPositionRTV(),
CurrentVelocityRTV(),
CurrentEmissiveRTV()
CurrentEmissiveRTV(),
CurrentSpecularRTV()
};
D3D12_CPU_DESCRIPTOR_HANDLE dsv = CurrentActiveSceneDepthDSV();
cl->OMSetRenderTargets(5, rtvs, FALSE, &dsv);
cl->OMSetRenderTargets(6, rtvs, FALSE, &dsv);
cl->RSSetViewports(1, &w.viewport);
cl->RSSetScissorRects(1, &w.scissor);
}
@@ -12206,6 +12481,7 @@ static void QD3D12_ResolveSceneToOutputAndEnterNativePhase(QD3D12Window& w)
QD3D12_TransitionResource(cl, w.sceneColorBuffers[w.frameIndex].Get(), w.sceneColorState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(cl, w.velocityBuffers[w.frameIndex].Get(), w.velocityBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(cl, w.specularBuffers[w.frameIndex].Get(), w.specularBufferState[w.frameIndex], D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(cl, w.depthBuffer.Get(), w.depthState, D3D12_RESOURCE_STATE_PIXEL_SHADER_RESOURCE);
if (useLightingUpscaleInput)
@@ -12271,9 +12547,10 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle)
ID3D12Resource* sceneNormal = window->normalBuffers[frameIndex].Get();
ID3D12Resource* scenePosition = window->positionBuffers[frameIndex].Get();
ID3D12Resource* sceneEmissive = window->emissiveBuffers[frameIndex].Get();
ID3D12Resource* sceneSpecular = window->specularBuffers[frameIndex].Get();
ID3D12Resource* sceneDepth = window->depthBuffer.Get();
if (!sceneColor || !sceneNormal || !scenePosition || !sceneEmissive || !sceneDepth)
if (!sceneColor || !sceneNormal || !scenePosition || !sceneEmissive || !sceneSpecular || !sceneDepth)
return;
QD3D12_TransitionResource(
@@ -12300,6 +12577,12 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle)
window->emissiveBufferState[frameIndex],
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(
cl,
sceneSpecular,
window->specularBufferState[frameIndex],
D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE);
QD3D12_TransitionResource(
cl,
sceneDepth,
@@ -12342,6 +12625,7 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle)
useDLSSRayReconstruction ? 0 : 1,
useDLSSRayReconstruction ? 0.0f : 1.0f);
glRaytracingLightingSetEmissiveInput(sceneEmissive, QD3D12_EmissiveFormat);
glRaytracingLightingSetSpecularInput(sceneSpecular, QD3D12_SpecularAlbedoFormat);
glRaytracingLightingPassDesc_t pass = {};
pass.albedoTexture = sceneColor;
@@ -12371,6 +12655,7 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle)
QD3D12_TransitionResource(cl, window->positionMsaaBuffers[frameIndex].Get(), window->positionMsaaState[frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, window->velocityMsaaBuffers[frameIndex].Get(), window->velocityMsaaState[frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, window->emissiveMsaaBuffers[frameIndex].Get(), window->emissiveMsaaState[frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, window->specularMsaaBuffers[frameIndex].Get(), window->specularMsaaState[frameIndex], D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(cl, window->depthMsaaBuffer.Get(), window->depthMsaaState, D3D12_RESOURCE_STATE_DEPTH_WRITE);
}
else
@@ -12399,6 +12684,12 @@ void glLightScene(glRaytracingSceneHandle_t sceneHandle)
window->emissiveBufferState[frameIndex],
D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(
cl,
sceneSpecular,
window->specularBufferState[frameIndex],
D3D12_RESOURCE_STATE_RENDER_TARGET);
QD3D12_TransitionResource(
cl,
sceneDepth,