diff --git a/src/renderer/atlas/BackendD3D.cpp b/src/renderer/atlas/BackendD3D.cpp index 51fabcf5be..fd1d9a6bc8 100644 --- a/src/renderer/atlas/BackendD3D.cpp +++ b/src/renderer/atlas/BackendD3D.cpp @@ -571,19 +571,30 @@ void BackendD3D::_recreateBackgroundColorBitmap(const RenderingPayload& p) _backgroundBitmapGeneration = {}; } -void BackendD3D::_recreateConstBuffer(const RenderingPayload& p) const +void BackendD3D::_recreateConstBuffer(const RenderingPayload& p) { { VSConstBuffer data{}; - data.positionScale = { 2.0f / p.s->targetSize.x, -2.0f / p.s->targetSize.y }; - data.padding = { p.s->misc->topLeftOffset.x, p.s->misc->topLeftOffset.y, 0.f, 0.f }; + data.positionScale = { + 2.0f / p.s->targetSize.x, + -2.0f / p.s->targetSize.y, + }; + data.positionOffset = { + data.positionScale.x * p.s->misc->topLeftOffset.x - 1.0f, + data.positionScale.y * p.s->misc->topLeftOffset.y + 1.0f, + }; p.deviceContext->UpdateSubresource(_vsConstantBuffer.get(), 0, nullptr, &data, 0, 0); } { PSConstBuffer data{}; - data.backgroundColor = colorFromU32Premultiply(p.s->misc->backgroundColor); - data.backgroundCellSize = { static_cast(p.s->font->cellSize.x), static_cast(p.s->font->cellSize.y) }; - data.backgroundCellCount = { static_cast(p.s->viewportCellCount.x), static_cast(p.s->viewportCellCount.y) }; + data.viewportScale = { + 1.0f / (p.s->font->cellSize.x * p.s->viewportCellCount.x), + 1.0f / (p.s->font->cellSize.y * p.s->viewportCellCount.y), + }; + data.viewportOffset = { + data.viewportScale.x * -p.s->misc->topLeftOffset.x, + data.viewportScale.y * -p.s->misc->topLeftOffset.y, + }; DWrite_GetGammaRatios(_gamma, data.gammaRatios); data.enhancedContrast = p.s->font->antialiasingMode == AntialiasingMode::ClearType ? _cleartypeEnhancedContrast : _grayscaleEnhancedContrast; data.underlineWidth = p.s->font->underline.height; @@ -595,6 +606,23 @@ void BackendD3D::_recreateConstBuffer(const RenderingPayload& p) const data.shadedGlyphDotSize = std::max(1.0f, std::roundf(std::max(p.s->font->cellSize.x / 12.0f, p.s->font->cellSize.y / 24.0f))); p.deviceContext->UpdateSubresource(_psConstantBuffer.get(), 0, nullptr, &data, 0, 0); } + { + const auto color = colorFromU32Premultiply(p.s->misc->backgroundColor); + const D3D11_SAMPLER_DESC desc{ + .Filter = D3D11_FILTER_MIN_MAG_MIP_POINT, + .AddressU = D3D11_TEXTURE_ADDRESS_BORDER, + .AddressV = D3D11_TEXTURE_ADDRESS_BORDER, + .AddressW = D3D11_TEXTURE_ADDRESS_BORDER, + .MipLODBias = 0, + .MaxAnisotropy = 1, + .ComparisonFunc = D3D11_COMPARISON_NEVER, + //.BorderColor = { color.x, color.y, color.z, color.w }, + .BorderColor = { 1.0f, 0.2f, 0.2f, 1.0f }, + .MinLOD = -FLT_MAX, + .MaxLOD = FLT_MAX, + }; + THROW_IF_FAILED(p.device->CreateSamplerState(&desc, _backgroundSampler.put())); + } } void BackendD3D::_setupDeviceContextState(const RenderingPayload& p) @@ -623,6 +651,7 @@ void BackendD3D::_setupDeviceContextState(const RenderingPayload& p) p.deviceContext->PSSetShader(_pixelShader.get(), nullptr, 0); p.deviceContext->PSSetConstantBuffers(0, 1, _psConstantBuffer.addressof()); p.deviceContext->PSSetShaderResources(0, 2, &resources[0]); + p.deviceContext->PSSetSamplers(0, 1, _backgroundSampler.addressof()); // OM: Output Merger p.deviceContext->OMSetBlendState(_blendState.get(), nullptr, 0xffffffff); @@ -1073,6 +1102,10 @@ void BackendD3D::_drawBackground(const RenderingPayload& p) _appendQuad() = { .shadingType = static_cast(ShadingType::Background), + .position = { + static_cast(lrintf(-p.s->misc->topLeftOffset.x)), + static_cast(lrintf(-p.s->misc->topLeftOffset.x)), + }, .size = p.s->targetSize, }; } @@ -2373,7 +2406,7 @@ void BackendD3D::_executeCustomShader(RenderingPayload& p) p.deviceContext->PSSetShader(_pixelShader.get(), nullptr, 0); p.deviceContext->PSSetConstantBuffers(0, 1, _psConstantBuffer.addressof()); p.deviceContext->PSSetShaderResources(0, 2, &resources[0]); - p.deviceContext->PSSetSamplers(0, 0, nullptr); + p.deviceContext->PSSetSamplers(0, 1, _backgroundSampler.addressof()); // OM: Output Merger p.deviceContext->OMSetBlendState(_blendState.get(), nullptr, 0xffffffff); diff --git a/src/renderer/atlas/BackendD3D.h b/src/renderer/atlas/BackendD3D.h index 6eb23f4faa..e83b67a191 100644 --- a/src/renderer/atlas/BackendD3D.h +++ b/src/renderer/atlas/BackendD3D.h @@ -29,17 +29,16 @@ namespace Microsoft::Console::Render::Atlas // padding so that it is {u32; u32; u32; <4 byte padding>; u32x2}. // * bool will probably not work the way you want it to, // because HLSL uses 32-bit bools and C++ doesn't. - alignas(sizeof(f32x4)) f32x4 padding; alignas(sizeof(f32x2)) f32x2 positionScale; + alignas(sizeof(f32x2)) f32x2 positionOffset; #pragma warning(suppress : 4324) // 'VSConstBuffer': structure was padded due to alignment specifier }; // WARNING: Same rules as for VSConstBuffer above apply. struct alignas(16) PSConstBuffer { - alignas(sizeof(f32x4)) f32x4 backgroundColor; - alignas(sizeof(f32x2)) f32x2 backgroundCellSize; - alignas(sizeof(f32x2)) f32x2 backgroundCellCount; + alignas(sizeof(f32x2)) f32x2 backgroundScale; + alignas(sizeof(f32x2)) f32x2 backgroundOffset; alignas(sizeof(f32x4)) f32 gammaRatios[4]{}; alignas(sizeof(f32)) f32 enhancedContrast = 0; alignas(sizeof(f32)) f32 underlineWidth = 0; @@ -231,7 +230,7 @@ namespace Microsoft::Console::Render::Atlas void _recreateCustomShader(const RenderingPayload& p); void _recreateCustomRenderTargetView(const RenderingPayload& p); void _recreateBackgroundColorBitmap(const RenderingPayload& p); - void _recreateConstBuffer(const RenderingPayload& p) const; + void _recreateConstBuffer(const RenderingPayload& p); void _setupDeviceContextState(const RenderingPayload& p); void _debugUpdateShaders(const RenderingPayload& p) noexcept; void _debugShowDirty(const RenderingPayload& p); @@ -292,6 +291,7 @@ namespace Microsoft::Console::Render::Atlas wil::com_ptr _backgroundBitmap; wil::com_ptr _backgroundBitmapView; + wil::com_ptr _backgroundSampler; til::generation_t _backgroundBitmapGeneration; wil::com_ptr _glyphAtlas; diff --git a/src/renderer/atlas/shader_ps.hlsl b/src/renderer/atlas/shader_ps.hlsl index a39ec79dc7..4bbf9d8c1c 100644 --- a/src/renderer/atlas/shader_ps.hlsl +++ b/src/renderer/atlas/shader_ps.hlsl @@ -6,9 +6,8 @@ cbuffer ConstBuffer : register(b0) { - float4 backgroundColor; - float2 backgroundCellSize; - float2 backgroundCellCount; + float2 backgroundScale; + float2 backgroundOffset; float4 gammaRatios; float enhancedContrast; float underlineWidth; @@ -17,6 +16,7 @@ cbuffer ConstBuffer : register(b0) float shadedGlyphDotSize; } +SamplerState backgroundSampler; Texture2D background : register(t0); Texture2D glyphAtlas : register(t1); @@ -37,8 +37,7 @@ Output main(PSData data) : SV_Target { case SHADING_TYPE_TEXT_BACKGROUND: { - float2 cell = data.position.xy / backgroundCellSize; - color = all(cell < backgroundCellCount) ? background[cell] : backgroundColor; + color = background.Sample(backgroundSampler, data.position.xy * backgroundScale + backgroundOffset); weights = float4(1, 1, 1, 1); break; } diff --git a/src/renderer/atlas/shader_vs.hlsl b/src/renderer/atlas/shader_vs.hlsl index 50ba9871f7..b72f8c12e5 100644 --- a/src/renderer/atlas/shader_vs.hlsl +++ b/src/renderer/atlas/shader_vs.hlsl @@ -5,8 +5,8 @@ cbuffer ConstBuffer : register(b0) { - float4 padding; float2 positionScale; + float2 positionOffset; } // clang-format off @@ -19,8 +19,8 @@ PSData main(VSData data) output.renditionScale = data.renditionScale; // positionScale is expected to be float2(2.0f / sizeInPixel.x, -2.0f / sizeInPixel.y). Together with the // addition below this will transform our "position" from pixel into normalized device coordinate (NDC) space. - output.position.xy = (padding.xy + data.position + data.vertex.xy * data.size) * positionScale + float2(-1.0f, 1.0f); + output.position.xy = (data.vertex * data.size + data.position) * positionScale + positionOffset; output.position.zw = float2(0, 1); - output.texcoord = data.texcoord + data.vertex.xy * data.size; + output.texcoord = data.vertex * data.size + data.texcoord; return output; }