From 93c787dcd486525ead1d655f00d530ef78c4c514 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Sun, 21 Jan 2018 12:01:52 -1000 Subject: [PATCH] Gamma correction for Vulkan, D3D, OpenGL --- glslang | 2 +- include/boo/graphicsdev/Vulkan.hpp | 6 +- lib/graphicsdev/D3D11.cpp | 325 ++++++++++++++------ lib/graphicsdev/D3D12.cpp | 410 ++++++++++++++++++------- lib/graphicsdev/GL.cpp | 65 ++-- lib/graphicsdev/Vulkan.cpp | 471 ++++++++++++++++++++--------- lib/win/ApplicationWin32.cpp | 2 - lib/win/WinCommon.hpp | 21 ++ lib/win/WindowWin32.cpp | 11 +- logvisor | 2 +- test/main.cpp | 19 +- 11 files changed, 940 insertions(+), 394 deletions(-) diff --git a/glslang b/glslang index 2edde66..82ead04 160000 --- a/glslang +++ b/glslang @@ -1 +1 @@ -Subproject commit 2edde6665d9a56ead5ea0e55b4e64d9a803e6164 +Subproject commit 82ead04c39c6a4b7fa153d692b26181091c43c15 diff --git a/include/boo/graphicsdev/Vulkan.hpp b/include/boo/graphicsdev/Vulkan.hpp index 34e6670..5c3483e 100644 --- a/include/boo/graphicsdev/Vulkan.hpp +++ b/include/boo/graphicsdev/Vulkan.hpp @@ -43,6 +43,7 @@ struct VulkanContext VkDescriptorSetLayout m_descSetLayout; VkPipelineLayout m_pipelinelayout; VkRenderPass m_pass; + VkRenderPass m_passColorOnly; VkCommandPool m_loadPool; VkCommandBuffer m_loadCmdBuf; VkFormat m_displayFormat; @@ -56,7 +57,10 @@ struct VulkanContext struct Buffer { VkImage m_image = VK_NULL_HANDLE; - VkImageLayout m_layout = VK_IMAGE_LAYOUT_UNDEFINED; + VkImageView m_colorView = VK_NULL_HANDLE; + VkFramebuffer m_framebuffer = VK_NULL_HANDLE; + VkRenderPassBeginInfo m_passBeginInfo = {}; + void setImage(VulkanContext* ctx, VkImage image, uint32_t width, uint32_t height); }; std::vector m_bufs; uint32_t m_backBuf = 0; diff --git a/lib/graphicsdev/D3D11.cpp b/lib/graphicsdev/D3D11.cpp index fe7e74e..35f8d9f 100644 --- a/lib/graphicsdev/D3D11.cpp +++ b/lib/graphicsdev/D3D11.cpp @@ -19,6 +19,46 @@ extern pD3DCompile D3DCompilePROC; +static const char* GammaVS = +"struct VertData\n" +"{\n" +" float4 posIn : POSITION;\n" +" float4 uvIn : UV;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 pos : SV_Position;\n" +" float2 uv : UV;\n" +"};\n" +"\n" +"VertToFrag main(in VertData v)\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.uv = v.uvIn.xy;\n" +" vtf.pos = v.posIn;\n" +" return vtf;\n" +"}\n"; + +static const char* GammaFS = +"struct VertToFrag\n" +"{\n" +" float4 pos : SV_Position;\n" +" float2 uv : UV;\n" +"};\n" +"\n" +"Texture2D screenTex : register(t0);\n" +"Texture2D gammaLUT : register(t1);\n" +"SamplerState samp : register(s2);\n" +"float4 main(in VertToFrag vtf) : SV_Target0\n" +"{\n" +" int4 tex = int4(saturate(screenTex.Sample(samp, vtf.uv)) * float4(65535.0, 65535.0, 65535.0, 65535.0));\n" +" float4 colorOut;\n" +" for (int i=0 ; i<3 ; ++i)\n" +" colorOut[i] = gammaLUT.Load(int3(tex[i] % 256, tex[i] / 256, 0)).r;\n" +" return colorOut;\n" +"}\n"; + namespace boo { static logvisor::Module Log("boo::D3D11"); @@ -138,6 +178,10 @@ class D3D11TextureS : public GraphicsDataNode case TextureFormat::I8: pfmt = DXGI_FORMAT_R8_UNORM; break; + case TextureFormat::I16: + pfmt = DXGI_FORMAT_R16_UNORM; + pxPitchNum = 2; + break; case TextureFormat::DXT1: pfmt = DXGI_FORMAT_BC1_UNORM; compressed = true; @@ -189,15 +233,20 @@ class D3D11TextureSA : public GraphicsDataNode { size_t pixelPitch; DXGI_FORMAT pixelFmt; - if (fmt == TextureFormat::RGBA8) + switch (fmt) { + case TextureFormat::RGBA8: pixelPitch = 4; pixelFmt = DXGI_FORMAT_R8G8B8A8_UNORM; - } - else if (fmt == TextureFormat::I8) - { + break; + case TextureFormat::I8: pixelPitch = 1; pixelFmt = DXGI_FORMAT_R8_UNORM; + break; + case TextureFormat::I16: + pixelPitch = 2; + pixelFmt = DXGI_FORMAT_R16_UNORM; + break; } CD3D11_TEXTURE2D_DESC desc(pixelFmt, width, height, layers, mips, @@ -260,6 +309,10 @@ class D3D11TextureD : public GraphicsDataNode pixelFmt = DXGI_FORMAT_R8_UNORM; m_pxPitch = 1; break; + case TextureFormat::I16: + pixelFmt = DXGI_FORMAT_R16_UNORM; + m_pxPitch = 2; + break; default: Log.report(logvisor::Fatal, "unsupported tex format"); } @@ -531,8 +584,8 @@ class D3D11ShaderPipeline : public GraphicsDataNode } CD3D11_RASTERIZER_DESC rasDesc(D3D11_FILL_SOLID, cullMode, true, - D3D11_DEFAULT_DEPTH_BIAS, D3D11_DEFAULT_DEPTH_BIAS_CLAMP, D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, - true, true, false, false); + D3D11_DEFAULT_DEPTH_BIAS, D3D11_DEFAULT_DEPTH_BIAS_CLAMP, + D3D11_DEFAULT_SLOPE_SCALED_DEPTH_BIAS, true, true, false, false); ThrowIfFailed(ctx->m_dev->CreateRasterizerState(&rasDesc, &m_rasState)); CD3D11_DEPTH_STENCIL_DESC dsDesc(D3D11_DEFAULT); @@ -919,81 +972,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue std::recursive_mutex m_dynamicLock; void ProcessDynamicLoads(ID3D11DeviceContext* ctx); - static void RenderingWorker(D3D11CommandQueue* self) - { - { - std::unique_lock lk(self->m_initmt); - } - self->m_initcv.notify_one(); - while (self->m_running) - { - { - std::unique_lock lk(self->m_mt); - self->m_cv.wait(lk); - if (!self->m_running) - break; - self->m_drawBuf = self->m_completeBuf; - auto& CmdList = self->m_cmdLists[self->m_drawBuf]; - - self->ProcessDynamicLoads(self->m_ctx->m_devCtx.Get()); - - if (self->m_texResizes.size()) - { - for (const auto& resize : self->m_texResizes) - resize.first->resize(self->m_ctx, resize.second.first, resize.second.second); - self->m_texResizes.clear(); - CmdList.reset(); - continue; - } - - if (self->m_windowCtx->m_needsFSTransition) - { - if (self->m_windowCtx->m_fs) - { - self->m_windowCtx->m_swapChain->SetFullscreenState(true, nullptr); - self->m_windowCtx->m_swapChain->ResizeTarget(&self->m_windowCtx->m_fsdesc); - } - else - self->m_windowCtx->m_swapChain->SetFullscreenState(false, nullptr); - - self->m_windowCtx->m_needsFSTransition = false; - CmdList.reset(); - continue; - } - - if (self->m_windowCtx->m_needsResize) - { - self->m_windowCtx->m_swapChain->ResizeBuffers(2, - self->m_windowCtx->width, self->m_windowCtx->height, - self->m_ctx->m_fbFormat, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); - self->m_windowCtx->m_needsResize = false; - CmdList.reset(); - continue; - } - } - - auto& CmdList = self->m_cmdLists[self->m_drawBuf]; - ID3D11CommandList* list = CmdList.list.Get(); - self->m_ctx->m_devCtx->ExecuteCommandList(list, false); - - D3D11TextureR* csource = CmdList.workDoPresent.cast(); - if (csource) - { - ComPtr dest; - ThrowIfFailed(self->m_windowCtx->m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &dest)); - - ID3D11Texture2D* src = csource->m_colorTex.Get(); - if (csource->m_samples > 1) - self->m_ctx->m_devCtx->ResolveSubresource(dest.Get(), 0, src, 0, self->m_ctx->m_fbFormat); - else - self->m_ctx->m_devCtx->CopyResource(dest.Get(), src); - - self->m_windowCtx->m_swapChain->Present(1, 0); - } - - CmdList.reset(); - } - } + static void RenderingWorker(D3D11CommandQueue* self); D3D11CommandQueue(D3D11Context* ctx, D3D11Context::Window* windowCtx, IGraphicsContext* parent) : m_ctx(ctx), m_windowCtx(windowCtx), m_parent(parent), @@ -1005,7 +984,7 @@ struct D3D11CommandQueue : IGraphicsCommandQueue ThrowIfFailed(ctx->m_dev->CreateDeferredContext1(0, &m_deferredCtx)); } - void startRenderer() {} + void startRenderer(); void stopRenderer() { @@ -1115,16 +1094,15 @@ struct D3D11CommandQueue : IGraphicsCommandQueue m_deferredCtx->DrawIndexedInstanced(count, instCount, start, 0, 0); } - void resolveBindTexture(const boo::ObjToken& texture, const SWindowRect& rect, - bool tlOrigin, int bindIdx, bool color, bool depth, bool clearDepth) + void _resolveBindTexture(ID3D11DeviceContext1* ctx, const D3D11TextureR* tex, const SWindowRect& rect, + bool tlOrigin, int bindIdx, bool color, bool depth) { - const D3D11TextureR* tex = texture.cast(); if (color && tex->m_colorBindCount) { if (tex->m_samples > 1) { - m_deferredCtx->ResolveSubresource(tex->m_colorBindTex[bindIdx].Get(), 0, tex->m_colorTex.Get(), 0, - m_ctx->m_fbFormat); + ctx->ResolveSubresource(tex->m_colorBindTex[bindIdx].Get(), 0, tex->m_colorTex.Get(), 0, + m_ctx->m_fbFormat); } else { @@ -1132,23 +1110,29 @@ struct D3D11CommandQueue : IGraphicsCommandQueue int y = tlOrigin ? intersectRect.location[1] : (tex->m_height - intersectRect.size[1] - intersectRect.location[1]); D3D11_BOX box = {UINT(intersectRect.location[0]), UINT(y), 0, UINT(intersectRect.location[0] + intersectRect.size[0]), UINT(y + intersectRect.size[1]), 1}; - m_deferredCtx->CopySubresourceRegion1(tex->m_colorBindTex[bindIdx].Get(), 0, box.left, box.top, 0, - tex->m_colorTex.Get(), 0, &box, D3D11_COPY_DISCARD); + ctx->CopySubresourceRegion1(tex->m_colorBindTex[bindIdx].Get(), 0, box.left, box.top, 0, + tex->m_colorTex.Get(), 0, &box, D3D11_COPY_DISCARD); } } if (depth && tex->m_depthBindCount) { if (tex->m_samples > 1) { - m_deferredCtx->ResolveSubresource(tex->m_depthBindTex[bindIdx].Get(), 0, tex->m_depthTex.Get(), 0, + ctx->ResolveSubresource(tex->m_depthBindTex[bindIdx].Get(), 0, tex->m_depthTex.Get(), 0, DXGI_FORMAT_D24_UNORM_S8_UINT); } else { - m_deferredCtx->CopyResource(tex->m_depthBindTex[bindIdx].Get(), tex->m_depthTex.Get()); + ctx->CopyResource(tex->m_depthBindTex[bindIdx].Get(), tex->m_depthTex.Get()); } } + } + void resolveBindTexture(const boo::ObjToken& texture, const SWindowRect& rect, + bool tlOrigin, int bindIdx, bool color, bool depth, bool clearDepth) + { + const D3D11TextureR* tex = texture.cast(); + _resolveBindTexture(m_deferredCtx.Get(), tex, rect, tlOrigin, bindIdx, color, depth); if (clearDepth) m_deferredCtx->ClearDepthStencilView(tex->m_dsv.Get(), D3D11_CLEAR_DEPTH, 0.0f, 0); } @@ -1244,6 +1228,43 @@ class D3D11DataFactory : public ID3DDataFactory, public GraphicsDataFactoryHead std::unordered_map> m_sharedShaders; std::unordered_map m_sourceToBinary; + float m_gamma = 1.f; + ObjToken m_gammaShader; + ObjToken m_gammaLUT; + ObjToken m_gammaVBO; + ObjToken m_gammaVFMT; + ObjToken m_gammaBinding; + void SetupGammaResources() + { + commitTransaction([this](IGraphicsDataFactory::Context& ctx) + { + const VertexElementDescriptor vfmt[] = { + {nullptr, nullptr, VertexSemantic::Position4}, + {nullptr, nullptr, VertexSemantic::UV4} + }; + m_gammaVFMT = ctx.newVertexFormat(2, vfmt); + m_gammaShader = static_cast(ctx).newShaderPipeline(GammaVS, GammaFS, + nullptr, nullptr, nullptr, m_gammaVFMT, BlendFactor::One, BlendFactor::Zero, + Primitive::TriStrips, ZTest::None, false, true, false, CullMode::None); + m_gammaLUT = ctx.newDynamicTexture(256, 256, TextureFormat::I16, TextureClampMode::ClampToEdge); + setDisplayGamma(1.f); + const struct Vert { + float pos[4]; + float uv[4]; + } verts[4] = { + {{-1.f, 1.f, 0.f, 1.f}, {0.f, 0.f, 0.f, 0.f}}, + {{ 1.f, 1.f, 0.f, 1.f}, {1.f, 0.f, 0.f, 0.f}}, + {{-1.f, -1.f, 0.f, 1.f}, {0.f, 1.f, 0.f, 0.f}}, + {{ 1.f, -1.f, 0.f, 1.f}, {1.f, 1.f, 0.f, 0.f}} + }; + m_gammaVBO = ctx.newStaticBuffer(BufferUse::Vertex, verts, 32, 4); + ObjToken texs[] = {{}, m_gammaLUT.get()}; + m_gammaBinding = ctx.newShaderDataBinding(m_gammaShader, m_gammaVFMT, m_gammaVBO.get(), {}, {}, + 0, nullptr, nullptr, 2, texs, nullptr, nullptr); + return true; + }); + } + public: D3D11DataFactory(IGraphicsContext* parent, D3D11Context* ctx) : m_parent(parent), m_ctx(ctx) @@ -1502,9 +1523,129 @@ public: m_sharedShaders.erase(binKey); } - void setDisplayGamma(float gamma) { /*UpdateGammaLUT(m_gammaLUT.get(), gamma);*/ } + void setDisplayGamma(float gamma) + { + if (m_ctx->m_fbFormat == DXGI_FORMAT_R16G16B16A16_FLOAT) + m_gamma = gamma * 2.2f; + else + m_gamma = gamma; + if (m_gamma != 1.f) + UpdateGammaLUT(m_gammaLUT.get(), m_gamma); + } }; +void D3D11CommandQueue::RenderingWorker(D3D11CommandQueue* self) +{ + { + std::unique_lock lk(self->m_initmt); + } + self->m_initcv.notify_one(); + D3D11DataFactory* dataFactory = static_cast(self->m_parent->getDataFactory()); + while (self->m_running) + { + { + std::unique_lock lk(self->m_mt); + self->m_cv.wait(lk); + if (!self->m_running) + break; + self->m_drawBuf = self->m_completeBuf; + auto& CmdList = self->m_cmdLists[self->m_drawBuf]; + + self->ProcessDynamicLoads(self->m_ctx->m_devCtx.Get()); + + if (self->m_texResizes.size()) + { + for (const auto& resize : self->m_texResizes) + resize.first->resize(self->m_ctx, resize.second.first, resize.second.second); + self->m_texResizes.clear(); + CmdList.reset(); + continue; + } + + if (self->m_windowCtx->m_needsFSTransition) + { + if (self->m_windowCtx->m_fs) + { + self->m_windowCtx->m_swapChain->SetFullscreenState(true, nullptr); + self->m_windowCtx->m_swapChain->ResizeTarget(&self->m_windowCtx->m_fsdesc); + } + else + self->m_windowCtx->m_swapChain->SetFullscreenState(false, nullptr); + + self->m_windowCtx->m_needsFSTransition = false; + CmdList.reset(); + continue; + } + + if (self->m_windowCtx->m_needsResize) + { + self->m_windowCtx->clearRTV(); + self->m_windowCtx->m_swapChain->ResizeBuffers(2, + self->m_windowCtx->width, self->m_windowCtx->height, + self->m_ctx->m_fbFormat, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH); + self->m_windowCtx->setupRTV(self->m_windowCtx->m_swapChain, self->m_ctx->m_dev.Get()); + self->m_windowCtx->m_needsResize = false; + CmdList.reset(); + continue; + } + } + + auto& CmdList = self->m_cmdLists[self->m_drawBuf]; + ID3D11CommandList* list = CmdList.list.Get(); + self->m_ctx->m_devCtx->ExecuteCommandList(list, false); + + if (D3D11TextureR* csource = CmdList.workDoPresent.cast()) + { +#ifndef NDEBUG + if (!csource->m_colorBindCount) + Log.report(logvisor::Fatal, + "texture provided to resolveDisplay() must have at least 1 color binding"); +#endif + + if (dataFactory->m_gamma != 1.f) + { + SWindowRect rect(0, 0, csource->m_width, csource->m_height); + self->_resolveBindTexture(self->m_ctx->m_devCtx.Get(), csource, rect, true, 0, true, false); + ID3D11RenderTargetView* rtv = self->m_windowCtx->m_swapChainRTV.Get(); + self->m_ctx->m_devCtx->OMSetRenderTargets(1, &rtv, nullptr); + + D3D11_VIEWPORT vp = {0.f, 0.f, FLOAT(csource->m_width), FLOAT(csource->m_height), 0.f, 1.f}; + self->m_ctx->m_devCtx->RSSetViewports(1, &vp); + D3D11_RECT d3drect = {0, 0, LONG(csource->m_width), LONG(csource->m_height)}; + self->m_ctx->m_devCtx->RSSetScissorRects(1, &d3drect); + ID3D11SamplerState* samp[] = {self->m_ctx->m_ss[0].Get(), + self->m_ctx->m_ss[1].Get(), + self->m_ctx->m_ss[2].Get()}; + self->m_ctx->m_devCtx->PSSetSamplers(0, 3, samp); + + D3D11ShaderDataBinding* gammaBinding = dataFactory->m_gammaBinding.cast(); + gammaBinding->m_texs[0].tex = CmdList.workDoPresent.get(); + gammaBinding->bind(self->m_ctx->m_devCtx.Get(), self->m_drawBuf); + self->m_ctx->m_devCtx->Draw(4, 0); + gammaBinding->m_texs[0].tex.reset(); + } + else + { + ComPtr dest = self->m_windowCtx->m_swapChainTex; + ID3D11Texture2D* src = csource->m_colorTex.Get(); + if (csource->m_samples > 1) + self->m_ctx->m_devCtx->ResolveSubresource(dest.Get(), 0, src, 0, self->m_ctx->m_fbFormat); + else + self->m_ctx->m_devCtx->CopyResource(dest.Get(), src); + } + + self->m_windowCtx->m_swapChain->Present(1, 0); + } + + CmdList.reset(); + } +} + +void D3D11CommandQueue::startRenderer() +{ + static_cast(m_parent->getDataFactory())->SetupGammaResources(); +} + void D3D11CommandQueue::execute() { /* Finish command list */ diff --git a/lib/graphicsdev/D3D12.cpp b/lib/graphicsdev/D3D12.cpp index d2524e7..010f61a 100644 --- a/lib/graphicsdev/D3D12.cpp +++ b/lib/graphicsdev/D3D12.cpp @@ -21,6 +21,46 @@ extern PFN_D3D12_SERIALIZE_ROOT_SIGNATURE D3D12SerializeRootSignaturePROC; extern pD3DCompile D3DCompilePROC; +static const char* GammaVS = +"struct VertData\n" +"{\n" +" float4 posIn : POSITION;\n" +" float4 uvIn : UV;\n" +"};\n" +"\n" +"struct VertToFrag\n" +"{\n" +" float4 pos : SV_Position;\n" +" float2 uv : UV;\n" +"};\n" +"\n" +"VertToFrag main(in VertData v)\n" +"{\n" +" VertToFrag vtf;\n" +" vtf.uv = v.uvIn.xy;\n" +" vtf.pos = v.posIn;\n" +" return vtf;\n" +"}\n"; + +static const char* GammaFS = +"struct VertToFrag\n" +"{\n" +" float4 pos : SV_Position;\n" +" float2 uv : UV;\n" +"};\n" +"\n" +"Texture2D screenTex : register(t0);\n" +"Texture2D gammaLUT : register(t1);\n" +"SamplerState samp : register(s2);\n" +"float4 main(in VertToFrag vtf) : SV_Target0\n" +"{\n" +" int4 tex = int4(saturate(screenTex.Sample(samp, vtf.uv)) * float4(65535.0, 65535.0, 65535.0, 65535.0));\n" +" float4 colorOut;\n" +" for (int i=0 ; i<3 ; ++i)\n" +" colorOut[i] = gammaLUT.Load(int3(tex[i] % 256, tex[i] / 256, 0)).r;\n" +" return colorOut;\n" +"}\n"; + namespace boo { static logvisor::Module Log("boo::D3D12"); @@ -203,6 +243,10 @@ class D3D12TextureS : public GraphicsDataNode case TextureFormat::I8: pfmt = DXGI_FORMAT_R8_UNORM; break; + case TextureFormat::I16: + pfmt = DXGI_FORMAT_R16_UNORM; + pxPitchNum = 2; + break; case TextureFormat::DXT1: pfmt = DXGI_FORMAT_BC1_UNORM; compressed = true; @@ -287,6 +331,10 @@ class D3D12TextureSA : public GraphicsDataNode pxPitch = 1; pixelFmt = DXGI_FORMAT_R8_UNORM; break; + case TextureFormat::I16: + pxPitch = 2; + pixelFmt = DXGI_FORMAT_R16_UNORM; + break; default: Log.report(logvisor::Fatal, "unsupported tex format"); } @@ -371,6 +419,10 @@ class D3D12TextureD : public GraphicsDataNode pixelFmt = DXGI_FORMAT_R8_UNORM; pxPitch = 1; break; + case TextureFormat::I16: + pixelFmt = DXGI_FORMAT_R16_UNORM; + pxPitch = 2; + break; default: Log.report(logvisor::Fatal, "unsupported tex format"); } @@ -448,10 +500,10 @@ class D3D12TextureR : public GraphicsDataNode rtvDim = D3D12_RTV_DIMENSION_TEXTURE2DMS; dsvDim = D3D12_DSV_DIMENSION_TEXTURE2DMS; rtvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(ctx->RGBATex2DFBViewDesc.Format, m_width, m_height, 1, 1, m_samples, - D3D11_STANDARD_MULTISAMPLE_PATTERN, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_TEXTURE_LAYOUT_UNKNOWN, + 0, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); dsvresdesc = CD3DX12_RESOURCE_DESC::Tex2D(DXGI_FORMAT_R24G8_TYPELESS, m_width, m_height, 1, 1, m_samples, - D3D11_STANDARD_MULTISAMPLE_PATTERN, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN, + 0, D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL, D3D12_TEXTURE_LAYOUT_UNKNOWN, D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT); } else @@ -749,7 +801,7 @@ class D3D12ShaderPipeline : public GraphicsDataNode desc.RTVFormats[0] = ctx->RGBATex2DFBViewDesc.Format; desc.DSVFormat = DXGI_FORMAT_D24_UNORM_S8_UINT; desc.SampleDesc.Count = ctx->m_sampleCount; - desc.SampleDesc.Quality = D3D11_STANDARD_MULTISAMPLE_PATTERN; + desc.SampleDesc.Quality = 0; if (pipeline) { desc.CachedPSO.pCachedBlob = pipeline->GetBufferPointer(); @@ -895,6 +947,17 @@ static const struct GreyTex2DViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC } } GreyTex2DViewDesc; +static const struct Grey16Tex2DViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC +{ + Grey16Tex2DViewDesc() + { + Format = DXGI_FORMAT_R16_UNORM; + ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D; + Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + Texture2D = {UINT(0), UINT(-1), UINT(0), 0.0f}; + } +} Grey16Tex2DViewDesc; + static const struct RGBATex2DArrayViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC { RGBATex2DArrayViewDesc() @@ -917,6 +980,17 @@ static const struct GreyTex2DArrayViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC } } GreyTex2DArrayViewDesc; +static const struct Grey16Tex2DArrayViewDesc : D3D12_SHADER_RESOURCE_VIEW_DESC +{ + Grey16Tex2DArrayViewDesc() + { + Format = DXGI_FORMAT_R16_UNORM; + ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; + Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING; + Texture2DArray = {UINT(0), UINT(1), 0, 0, UINT(0), 0.0f}; + } +} Grey16Tex2DArrayViewDesc; + static ID3D12Resource* GetTextureGPUResource(D3D12Context* ctx, const ITexture* tex, int idx, int bindIdx, bool depth, D3D12_SHADER_RESOURCE_VIEW_DESC& descOut) { @@ -933,6 +1007,9 @@ static ID3D12Resource* GetTextureGPUResource(D3D12Context* ctx, const ITexture* case TextureFormat::I8: descOut = GreyTex2DViewDesc; break; + case TextureFormat::I16: + descOut = Grey16Tex2DViewDesc; + break; default:break; } descOut.Texture2D.MipLevels = 1; @@ -949,6 +1026,9 @@ static ID3D12Resource* GetTextureGPUResource(D3D12Context* ctx, const ITexture* case TextureFormat::I8: descOut = GreyTex2DViewDesc; break; + case TextureFormat::I16: + descOut = Grey16Tex2DViewDesc; + break; case TextureFormat::DXT1: descOut = DXTTex2DViewDesc; break; @@ -968,6 +1048,9 @@ static ID3D12Resource* GetTextureGPUResource(D3D12Context* ctx, const ITexture* case TextureFormat::I8: descOut = GreyTex2DArrayViewDesc; break; + case TextureFormat::I16: + descOut = Grey16Tex2DArrayViewDesc; + break; default:break; } descOut.Texture2DArray.ArraySize = ctex->layers(); @@ -1284,17 +1367,8 @@ struct D3D12CommandQueue : IGraphicsCommandQueue nullptr, __uuidof(ID3D12GraphicsCommandList), &m_dynamicCmdList)); } - void startRenderer() {} - - void stopRenderer() - { - m_running = false; - if (m_fence->GetCompletedValue() < m_submittedFenceVal) - { - ThrowIfFailed(m_fence->SetEventOnCompletion(m_submittedFenceVal, m_renderFenceHandle)); - WaitForSingleObject(m_renderFenceHandle, INFINITE); - } - } + void startRenderer(); + void stopRenderer(); ~D3D12CommandQueue() { @@ -1473,98 +1547,7 @@ struct D3D12CommandQueue : IGraphicsCommandQueue } bool m_doPresent = false; - void resolveDisplay(const boo::ObjToken& source) - { - D3D12TextureR* csource = source.cast(); - - if (m_windowCtx->m_needsResize) - { - UINT nodeMasks[] = {0,0}; - IUnknown* const queues[] = {m_ctx->m_q.Get(), m_ctx->m_q.Get()}; - m_windowCtx->m_swapChain->ResizeBuffers1(2, m_windowCtx->width, m_windowCtx->height, - m_ctx->RGBATex2DFBViewDesc.Format, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH, nodeMasks, queues); - m_windowCtx->m_backBuf = m_windowCtx->m_swapChain->GetCurrentBackBufferIndex(); - m_windowCtx->m_needsResize = false; - } - - ComPtr dest; - ThrowIfFailed(m_windowCtx->m_swapChain->GetBuffer(m_windowCtx->m_backBuf, __uuidof(ID3D12Resource), &dest)); - - ID3D12Resource* src = csource->m_colorTex.Get(); - D3D12_RESOURCE_STATES srcState = D3D12_RESOURCE_STATE_COPY_SOURCE; - if (m_boundTarget.get() == csource) - srcState = D3D12_RESOURCE_STATE_RENDER_TARGET; - - if (csource->m_samples > 1) - { - D3D12_RESOURCE_BARRIER msaaSetup[] = - { - CD3DX12_RESOURCE_BARRIER::Transition(src, - srcState, D3D12_RESOURCE_STATE_RESOLVE_SOURCE), - CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), - D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST) - }; - m_cmdList->ResourceBarrier(2, msaaSetup); - - m_cmdList->ResolveSubresource(dest.Get(), 0, src, 0, m_ctx->RGBATex2DFBViewDesc.Format); - - D3D12_RESOURCE_BARRIER msaaTeardown[] = - { - CD3DX12_RESOURCE_BARRIER::Transition(src, - D3D12_RESOURCE_STATE_RESOLVE_SOURCE, srcState), - CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), - D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT) - }; - m_cmdList->ResourceBarrier(2, msaaTeardown); - } - else - { - if (srcState != D3D12_RESOURCE_STATE_COPY_SOURCE) - { - D3D12_RESOURCE_BARRIER copySetup[] = - { - CD3DX12_RESOURCE_BARRIER::Transition(src, - srcState, D3D12_RESOURCE_STATE_COPY_SOURCE), - CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), - D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST) - }; - m_cmdList->ResourceBarrier(2, copySetup); - } - else - { - D3D12_RESOURCE_BARRIER copySetup[] = - { - CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), - D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST) - }; - m_cmdList->ResourceBarrier(1, copySetup); - } - - m_cmdList->CopyResource(dest.Get(), src); - - if (srcState != D3D12_RESOURCE_STATE_COPY_SOURCE) - { - D3D12_RESOURCE_BARRIER copyTeardown[] = - { - CD3DX12_RESOURCE_BARRIER::Transition(src, - D3D12_RESOURCE_STATE_COPY_SOURCE, srcState), - CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), - D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT) - }; - m_cmdList->ResourceBarrier(2, copyTeardown); - } - else - { - D3D12_RESOURCE_BARRIER copyTeardown[] = - { - CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), - D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT) - }; - m_cmdList->ResourceBarrier(1, copyTeardown); - } - } - m_doPresent = true; - } + void resolveDisplay(const boo::ObjToken& source); UINT64 m_submittedFenceVal = 0; void execute(); @@ -1667,6 +1650,43 @@ class D3D12DataFactory : public ID3DDataFactory, public GraphicsDataFactoryHead std::unordered_map> m_sharedShaders; std::unordered_map m_sourceToBinary; + float m_gamma = 1.f; + ObjToken m_gammaShader; + ObjToken m_gammaLUT; + ObjToken m_gammaVBO; + ObjToken m_gammaVFMT; + ObjToken m_gammaBinding; + void SetupGammaResources() + { + commitTransaction([this](IGraphicsDataFactory::Context& ctx) + { + const VertexElementDescriptor vfmt[] = { + {nullptr, nullptr, VertexSemantic::Position4}, + {nullptr, nullptr, VertexSemantic::UV4} + }; + m_gammaVFMT = ctx.newVertexFormat(2, vfmt); + m_gammaShader = static_cast(ctx).newShaderPipeline(GammaVS, GammaFS, + nullptr, nullptr, nullptr, m_gammaVFMT, BlendFactor::One, BlendFactor::Zero, + Primitive::TriStrips, ZTest::None, false, true, false, CullMode::None); + m_gammaLUT = ctx.newDynamicTexture(256, 256, TextureFormat::I16, TextureClampMode::ClampToEdge); + setDisplayGamma(1.f); + const struct Vert { + float pos[4]; + float uv[4]; + } verts[4] = { + {{-1.f, 1.f, 0.f, 1.f}, {0.f, 0.f, 0.f, 0.f}}, + {{ 1.f, 1.f, 0.f, 1.f}, {1.f, 0.f, 0.f, 0.f}}, + {{-1.f, -1.f, 0.f, 1.f}, {0.f, 1.f, 0.f, 0.f}}, + {{ 1.f, -1.f, 0.f, 1.f}, {1.f, 1.f, 0.f, 0.f}} + }; + m_gammaVBO = ctx.newStaticBuffer(BufferUse::Vertex, verts, 32, 4); + ObjToken texs[] = {{}, m_gammaLUT.get()}; + m_gammaBinding = ctx.newShaderDataBinding(m_gammaShader, m_gammaVFMT, m_gammaVBO.get(), {}, {}, + 0, nullptr, nullptr, 2, texs, nullptr, nullptr); + return true; + }); + } + public: D3D12DataFactory(IGraphicsContext* parent, D3D12Context* ctx) : m_parent(parent), m_ctx(ctx) @@ -2089,9 +2109,185 @@ public: m_sharedShaders.erase(binKey); } - void setDisplayGamma(float gamma) { /*UpdateGammaLUT(m_gammaLUT.get(), gamma);*/ } + void setDisplayGamma(float gamma) + { + if (m_ctx->RGBATex2DFBViewDesc.Format == DXGI_FORMAT_R16G16B16A16_FLOAT) + m_gamma = gamma * 2.2f; + else + m_gamma = gamma; + if (m_gamma != 1.f) + UpdateGammaLUT(m_gammaLUT.get(), m_gamma); + } }; +void D3D12CommandQueue::startRenderer() +{ + static_cast(m_parent->getDataFactory())->SetupGammaResources(); +} + +void D3D12CommandQueue::stopRenderer() +{ + m_running = false; + if (m_fence->GetCompletedValue() < m_submittedFenceVal) + { + ThrowIfFailed(m_fence->SetEventOnCompletion(m_submittedFenceVal, m_renderFenceHandle)); + WaitForSingleObject(m_renderFenceHandle, INFINITE); + } + /* + D3D12DataFactory* dataFactory = static_cast(m_parent->getDataFactory()); + dataFactory->m_gammaShader.reset(); + dataFactory->m_gammaLUT.reset(); + dataFactory->m_gammaVBO.reset(); + dataFactory->m_gammaVFMT.reset(); + dataFactory->m_gammaBinding.reset(); + */ +} + +void D3D12CommandQueue::resolveDisplay(const boo::ObjToken& source) +{ + D3D12TextureR* csource = source.cast(); +#ifndef NDEBUG + if (!csource->m_colorBindCount) + Log.report(logvisor::Fatal, + "texture provided to resolveDisplay() must have at least 1 color binding"); +#endif + + if (m_windowCtx->m_needsResize) + { + UINT nodeMasks[] = {0,0}; + IUnknown* const queues[] = {m_ctx->m_q.Get(), m_ctx->m_q.Get()}; + m_windowCtx->m_swapChain->ResizeBuffers1(2, m_windowCtx->width, m_windowCtx->height, + m_ctx->RGBATex2DFBViewDesc.Format, DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH, nodeMasks, queues); + m_windowCtx->m_backBuf = m_windowCtx->m_swapChain->GetCurrentBackBufferIndex(); + m_windowCtx->m_rtvHeaps.clear(); + m_windowCtx->m_needsResize = false; + return; + } + + ComPtr dest; + ThrowIfFailed(m_windowCtx->m_swapChain->GetBuffer(m_windowCtx->m_backBuf, __uuidof(ID3D12Resource), &dest)); + + ID3D12Resource* src = csource->m_colorTex.Get(); + D3D12_RESOURCE_STATES srcState = D3D12_RESOURCE_STATE_COPY_SOURCE; + if (m_boundTarget.get() == csource) + srcState = D3D12_RESOURCE_STATE_RENDER_TARGET; + + D3D12DataFactory* dataFactory = static_cast(m_parent->getDataFactory()); + if (dataFactory->m_gamma != 1.f) + { + SWindowRect rect(0, 0, csource->m_width, csource->m_height); + resolveBindTexture(source, rect, true, 0, true, false, false); + + auto search = m_windowCtx->m_rtvHeaps.find(dest.Get()); + if (search == m_windowCtx->m_rtvHeaps.end()) + { + ComPtr rtvHeap; + D3D12_DESCRIPTOR_HEAP_DESC rtvdesc = {D3D12_DESCRIPTOR_HEAP_TYPE_RTV, 1}; + ThrowIfFailed(m_ctx->m_dev->CreateDescriptorHeap(&rtvdesc, __uuidof(ID3D12DescriptorHeap), &rtvHeap)); + + D3D12_RENDER_TARGET_VIEW_DESC rtvvdesc = {m_ctx->RGBATex2DFBViewDesc.Format, D3D12_RTV_DIMENSION_TEXTURE2D}; + m_ctx->m_dev->CreateRenderTargetView(dest.Get(), &rtvvdesc, rtvHeap->GetCPUDescriptorHandleForHeapStart()); + + search = m_windowCtx->m_rtvHeaps.insert(std::make_pair(dest.Get(), rtvHeap)).first; + } + + D3D12_RESOURCE_BARRIER gammaSetup[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET) + }; + m_cmdList->ResourceBarrier(1, gammaSetup); + + m_cmdList->OMSetRenderTargets(1, &search->second->GetCPUDescriptorHandleForHeapStart(), false, nullptr); + + D3D12ShaderDataBinding* gammaBinding = dataFactory->m_gammaBinding.cast(); + gammaBinding->m_texs[0].tex = source.get(); + gammaBinding->bind(m_ctx, m_cmdList.Get(), m_fillBuf); + m_cmdList->DrawInstanced(4, 1, 0, 0); + gammaBinding->m_texs[0].tex.reset(); + + D3D12_RESOURCE_BARRIER gammaTeardown[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT) + }; + m_cmdList->ResourceBarrier(1, gammaTeardown); + } + else + { + if (csource->m_samples > 1) + { + D3D12_RESOURCE_BARRIER msaaSetup[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + srcState, D3D12_RESOURCE_STATE_RESOLVE_SOURCE), + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RESOLVE_DEST) + }; + m_cmdList->ResourceBarrier(2, msaaSetup); + + m_cmdList->ResolveSubresource(dest.Get(), 0, src, 0, m_ctx->RGBATex2DFBViewDesc.Format); + + D3D12_RESOURCE_BARRIER msaaTeardown[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + D3D12_RESOURCE_STATE_RESOLVE_SOURCE, srcState), + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_RESOLVE_DEST, D3D12_RESOURCE_STATE_PRESENT) + }; + m_cmdList->ResourceBarrier(2, msaaTeardown); + } + else + { + if (srcState != D3D12_RESOURCE_STATE_COPY_SOURCE) + { + D3D12_RESOURCE_BARRIER copySetup[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + srcState, D3D12_RESOURCE_STATE_COPY_SOURCE), + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST) + }; + m_cmdList->ResourceBarrier(2, copySetup); + } + else + { + D3D12_RESOURCE_BARRIER copySetup[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_COPY_DEST) + }; + m_cmdList->ResourceBarrier(1, copySetup); + } + + m_cmdList->CopyResource(dest.Get(), src); + + if (srcState != D3D12_RESOURCE_STATE_COPY_SOURCE) + { + D3D12_RESOURCE_BARRIER copyTeardown[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(src, + D3D12_RESOURCE_STATE_COPY_SOURCE, srcState), + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT) + }; + m_cmdList->ResourceBarrier(2, copyTeardown); + } + else + { + D3D12_RESOURCE_BARRIER copyTeardown[] = + { + CD3DX12_RESOURCE_BARRIER::Transition(dest.Get(), + D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_PRESENT) + }; + m_cmdList->ResourceBarrier(1, copyTeardown); + } + } + } + + m_doPresent = true; +} + void D3D12CommandQueue::execute() { if (!m_running) diff --git a/lib/graphicsdev/GL.cpp b/lib/graphicsdev/GL.cpp index 365fc63..e9ed53a 100644 --- a/lib/graphicsdev/GL.cpp +++ b/lib/graphicsdev/GL.cpp @@ -50,9 +50,9 @@ BOO_GLSL_BINDING_HEAD "TBINDING1 uniform sampler2D gammaLUT;\n" "void main()\n" "{\n" -" ivec4 linScale = ivec4(texture(screenTex, vtf.uv) * vec4(65535.0));\n" +" ivec4 tex = ivec4(texture(screenTex, vtf.uv) * 65535.0);\n" " for (int i=0 ; i<3 ; ++i)\n" -" colorOut[i] = texelFetch(gammaLUT, ivec2(linScale[i] % 256, linScale[i] / 256), 0).r;\n" +" colorOut[i] = texelFetch(gammaLUT, ivec2(tex[i] % 256, tex[i] / 256), 0).r;\n" "}\n"; namespace boo @@ -76,6 +76,7 @@ class GLDataFactoryImpl : public GLDataFactory, public GraphicsDataFactoryHead GLContext* m_glCtx; std::unordered_map> m_sharedShaders; + float m_gamma = 1.f; ObjToken m_gammaShader; ObjToken m_gammaLUT; ObjToken m_gammaVBO; @@ -89,7 +90,6 @@ class GLDataFactoryImpl : public GLDataFactory, public GraphicsDataFactoryHead 2, texNames, 0, nullptr, BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips, ZTest::None, false, true, false, CullMode::None); m_gammaLUT = ctx.newDynamicTexture(256, 256, TextureFormat::I16, TextureClampMode::ClampToEdge); - UpdateGammaLUT(m_gammaLUT.get(), 1.0f); const struct Vert { float pos[4]; float uv[4]; @@ -119,7 +119,12 @@ public: ObjToken newPoolBuffer(BufferUse use, size_t stride, size_t count); void _unregisterShareableShader(uint64_t srcKey, uint64_t binKey) { m_sharedShaders.erase(srcKey); } - void setDisplayGamma(float gamma) { UpdateGammaLUT(m_gammaLUT.get(), gamma); } + void setDisplayGamma(float gamma) + { + m_gamma = gamma; + if (gamma != 1.f) + UpdateGammaLUT(m_gammaLUT.get(), gamma); + } }; static const GLenum USE_TABLE[] = @@ -1494,41 +1499,43 @@ struct GLCommandQueue : IGraphicsCommandQueue { if (const GLTextureR* tex = cmd.source.cast()) { -#if 1 #ifndef NDEBUG if (!tex->m_colorBindCount) Log.report(logvisor::Fatal, "texture provided to resolveDisplay() must have at least 1 color binding"); #endif - glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); - if (tex->m_samples <= 1) + if (dataFactory->m_gamma != 1.f) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, tex->m_texs[0]); + glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); + if (tex->m_samples <= 1) + { + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, tex->m_texs[0]); + } + else + { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_bindFBOs[0][0]); + glBlitFramebuffer(0, 0, + tex->m_width, tex->m_height, + 0, 0, + tex->m_width, tex->m_height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + tex->bind(0, 0, false); + } + + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + dataFactory->m_gammaShader.cast()->bind(); + dataFactory->m_gammaVFMT.cast()->bind(self->m_drawBuf); + dataFactory->m_gammaLUT.cast()->bind(1, self->m_drawBuf); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); } else { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, tex->m_bindFBOs[0][0]); - glBlitFramebuffer(0, 0, - tex->m_width, tex->m_height, - 0, 0, - tex->m_width, tex->m_height, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - tex->bind(0, 0, false); + glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, tex->m_width, tex->m_height, 0, 0, + tex->m_width, tex->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); } - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - dataFactory->m_gammaShader.cast()->bind(); - dataFactory->m_gammaVFMT.cast()->bind(self->m_drawBuf); - dataFactory->m_gammaLUT.cast()->bind(1, self->m_drawBuf); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - -#else - glBindFramebuffer(GL_READ_FRAMEBUFFER, tex->m_fbo); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBlitFramebuffer(0, 0, tex->m_width, tex->m_height, 0, 0, - tex->m_width, tex->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST); -#endif } self->m_parent->present(); break; diff --git a/lib/graphicsdev/Vulkan.cpp b/lib/graphicsdev/Vulkan.cpp index ab42fb8..e50590f 100644 --- a/lib/graphicsdev/Vulkan.cpp +++ b/lib/graphicsdev/Vulkan.cpp @@ -17,6 +17,43 @@ #undef max #undef None +static const char* GammaVS = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"layout(location=0) in vec4 posIn;\n" +"layout(location=1) in vec4 uvIn;\n" +"\n" +"struct VertToFrag\n" +"{\n" +" vec2 uv;\n" +"};\n" +"\n" +"SBINDING(0) out VertToFrag vtf;\n" +"void main()\n" +"{\n" +" vtf.uv = uvIn.xy;\n" +" gl_Position = posIn;\n" +"}\n"; + +static const char* GammaFS = +"#version 330\n" +BOO_GLSL_BINDING_HEAD +"struct VertToFrag\n" +"{\n" +" vec2 uv;\n" +"};\n" +"\n" +"SBINDING(0) in VertToFrag vtf;\n" +"layout(location=0) out vec4 colorOut;\n" +"TBINDING0 uniform sampler2D screenTex;\n" +"TBINDING1 uniform sampler2D gammaLUT;\n" +"void main()\n" +"{\n" +" ivec4 tex = ivec4(texture(screenTex, vtf.uv) * 65535.0);\n" +" for (int i=0 ; i<3 ; ++i)\n" +" colorOut[i] = texelFetch(gammaLUT, ivec2(tex[i] % 256, tex[i] / 256), 0).r;\n" +"}\n"; + namespace boo { static logvisor::Module Log("boo::Vulkan"); @@ -42,6 +79,43 @@ class VulkanDataFactoryImpl : public VulkanDataFactory, public GraphicsDataFacto VulkanContext* m_ctx; std::unordered_map> m_sharedShaders; std::vector m_texUnis; + + float m_gamma = 1.f; + ObjToken m_gammaShader; + ObjToken m_gammaLUT; + ObjToken m_gammaVBO; + ObjToken m_gammaVFMT; + ObjToken m_gammaBinding; + void SetupGammaResources() + { + commitTransaction([this](IGraphicsDataFactory::Context& ctx) + { + const VertexElementDescriptor vfmt[] = { + {nullptr, nullptr, VertexSemantic::Position4}, + {nullptr, nullptr, VertexSemantic::UV4} + }; + m_gammaVFMT = ctx.newVertexFormat(2, vfmt); + m_gammaShader = static_cast(ctx).newShaderPipeline(GammaVS, GammaFS, + m_gammaVFMT, BlendFactor::One, BlendFactor::Zero, + Primitive::TriStrips, ZTest::None, false, true, false, CullMode::None); + m_gammaLUT = ctx.newDynamicTexture(256, 256, TextureFormat::I16, TextureClampMode::ClampToEdge); + const struct Vert { + float pos[4]; + float uv[4]; + } verts[4] = { + {{-1.f, -1.f, 0.f, 1.f}, {0.f, 0.f, 0.f, 0.f}}, + {{ 1.f, -1.f, 0.f, 1.f}, {1.f, 0.f, 0.f, 0.f}}, + {{-1.f, 1.f, 0.f, 1.f}, {0.f, 1.f, 0.f, 0.f}}, + {{ 1.f, 1.f, 0.f, 1.f}, {1.f, 1.f, 0.f, 0.f}} + }; + m_gammaVBO = ctx.newStaticBuffer(BufferUse::Vertex, verts, 32, 4); + ObjToken texs[] = {{}, m_gammaLUT.get()}; + m_gammaBinding = ctx.newShaderDataBinding(m_gammaShader, m_gammaVFMT, m_gammaVBO.get(), {}, {}, + 0, nullptr, nullptr, 2, texs, nullptr, nullptr); + return true; + }); + } + public: std::unordered_map m_sourceToBinary; VulkanDataFactoryImpl(IGraphicsContext* parent, VulkanContext* ctx); @@ -60,7 +134,12 @@ public: m_sharedShaders.erase(binKey); } - void setDisplayGamma(float gamma) { /*UpdateGammaLUT(m_gammaLUT.get(), gamma);*/ } + void setDisplayGamma(float gamma) + { + m_gamma = gamma; + if (gamma != 1.f) + UpdateGammaLUT(m_gammaLUT.get(), gamma); + } }; static inline void ThrowIfFailed(VkResult res) @@ -474,6 +553,57 @@ void VulkanContext::initDevice() m_gpuProps.driverVersion & 0b111111111111); } +void VulkanContext::Window::SwapChain::Buffer::setImage +(VulkanContext* ctx, VkImage image, uint32_t width, uint32_t height) +{ + m_image = image; + if (m_colorView) + vk::DestroyImageView(ctx->m_dev, m_colorView, nullptr); + if (m_framebuffer) + vk::DestroyFramebuffer(ctx->m_dev, m_framebuffer, nullptr); + + /* Create resource views */ + VkImageViewCreateInfo viewCreateInfo = {}; + viewCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + viewCreateInfo.pNext = nullptr; + viewCreateInfo.image = m_image; + viewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; + viewCreateInfo.format = ctx->m_displayFormat; + viewCreateInfo.components.r = VK_COMPONENT_SWIZZLE_R; + viewCreateInfo.components.g = VK_COMPONENT_SWIZZLE_G; + viewCreateInfo.components.b = VK_COMPONENT_SWIZZLE_B; + viewCreateInfo.components.a = VK_COMPONENT_SWIZZLE_A; + viewCreateInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + viewCreateInfo.subresourceRange.baseMipLevel = 0; + viewCreateInfo.subresourceRange.levelCount = 1; + viewCreateInfo.subresourceRange.baseArrayLayer = 0; + viewCreateInfo.subresourceRange.layerCount = 1; + ThrowIfFailed(vk::CreateImageView(ctx->m_dev, &viewCreateInfo, nullptr, &m_colorView)); + + /* framebuffer */ + VkFramebufferCreateInfo fbCreateInfo = {}; + fbCreateInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; + fbCreateInfo.pNext = nullptr; + fbCreateInfo.renderPass = ctx->m_passColorOnly; + fbCreateInfo.attachmentCount = 1; + fbCreateInfo.width = width; + fbCreateInfo.height = height; + fbCreateInfo.layers = 1; + fbCreateInfo.pAttachments = &m_colorView; + ThrowIfFailed(vk::CreateFramebuffer(ctx->m_dev, &fbCreateInfo, nullptr, &m_framebuffer)); + + m_passBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + m_passBeginInfo.pNext = nullptr; + m_passBeginInfo.renderPass = ctx->m_passColorOnly; + m_passBeginInfo.framebuffer = m_framebuffer; + m_passBeginInfo.renderArea.offset.x = 0; + m_passBeginInfo.renderArea.offset.y = 0; + m_passBeginInfo.renderArea.extent.width = width; + m_passBeginInfo.renderArea.extent.height = height; + m_passBeginInfo.clearValueCount = 0; + m_passBeginInfo.pClearValues = nullptr; +} + void VulkanContext::initSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR surface, VkFormat format, VkColorSpaceKHR colorspace) { @@ -553,7 +683,7 @@ void VulkanContext::initSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR swapChainInfo.oldSwapchain = nullptr; swapChainInfo.clipped = true; swapChainInfo.imageColorSpace = colorspace; - swapChainInfo.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT; + swapChainInfo.imageUsage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; swapChainInfo.queueFamilyIndexCount = 0; swapChainInfo.pQueueFamilyIndices = nullptr; @@ -604,12 +734,90 @@ void VulkanContext::initSwapChain(VulkanContext::Window& windowCtx, VkSurfaceKHR else m_anisotropy = 1; + VkDescriptorSetLayoutBinding layoutBindings[BOO_GLSL_MAX_UNIFORM_COUNT + BOO_GLSL_MAX_TEXTURE_COUNT]; + for (int i=0 ; i case TextureFormat::I8: pfmt = VK_FORMAT_R8_UNORM; break; + case TextureFormat::I16: + pfmt = VK_FORMAT_R16_UNORM; + m_pixelPitchNum = 2; + break; case TextureFormat::DXT1: pfmt = VK_FORMAT_BC1_RGBA_UNORM_BLOCK; m_pixelPitchNum = 1; @@ -1204,6 +1416,10 @@ class VulkanTextureSA : public GraphicsDataNode case TextureFormat::I8: pfmt = VK_FORMAT_R8_UNORM; break; + case TextureFormat::I16: + pfmt = VK_FORMAT_R16_UNORM; + m_pixelPitchNum = 2; + break; default: Log.report(logvisor::Fatal, "unsupported tex format"); } @@ -1409,6 +1625,10 @@ class VulkanTextureD : public GraphicsDataNode pfmt = VK_FORMAT_R8_UNORM; m_cpuSz = width * height; break; + case TextureFormat::I16: + pfmt = VK_FORMAT_R16_UNORM; + m_cpuSz = width * height * 2; + break; default: Log.report(logvisor::Fatal, "unsupported tex format"); } @@ -1563,7 +1783,6 @@ class VulkanTextureR : public GraphicsDataNode size_t m_height = 0; VkSampleCountFlags m_samplesColor, m_samplesDepth; - TextureClampMode m_clampMode; size_t m_colorBindCount; size_t m_depthBindCount; @@ -1751,7 +1970,6 @@ class VulkanTextureR : public GraphicsDataNode m_width(width), m_height(height), m_samplesColor(ctx->m_sampleCountColor), m_samplesDepth(ctx->m_sampleCountDepth), - m_clampMode(clampMode), m_colorBindCount(colorBindCount), m_depthBindCount(depthBindCount) { @@ -1762,7 +1980,7 @@ class VulkanTextureR : public GraphicsDataNode if (m_samplesColor == 0) m_samplesColor = 1; if (m_samplesDepth == 0) m_samplesDepth = 1; - setClampMode(m_clampMode); + setClampMode(clampMode); Setup(ctx); } public: @@ -1970,10 +2188,13 @@ public: } VulkanShaderPipeline& operator=(const VulkanShaderPipeline&) = delete; VulkanShaderPipeline(const VulkanShaderPipeline&) = delete; - VkPipeline bind() const + VkPipeline bind(VkRenderPass rPass = 0) const { if (!m_pipeline) { + if (!rPass) + rPass = m_ctx->m_pass; + VkCullModeFlagBits cullMode; switch (m_culling) { @@ -2122,7 +2343,7 @@ public: pipelineCreateInfo.pColorBlendState = &colorBlendInfo; pipelineCreateInfo.pDynamicState = &dynamicState; pipelineCreateInfo.layout = m_ctx->m_pipelinelayout; - pipelineCreateInfo.renderPass = m_ctx->m_pass; + pipelineCreateInfo.renderPass = rPass; ThrowIfFailed(vk::CreateGraphicsPipelines(m_ctx->m_dev, m_pipelineCache, 1, &pipelineCreateInfo, nullptr, &m_pipeline)); @@ -2440,7 +2661,7 @@ struct VulkanShaderDataBinding : GraphicsDataNode #endif } - void bind(VkCommandBuffer cmdBuf, int b) + void bind(VkCommandBuffer cmdBuf, int b, VkRenderPass rPass = 0) { #ifndef NDEBUG if (!m_committed) @@ -2477,7 +2698,7 @@ struct VulkanShaderDataBinding : GraphicsDataNode if (totalWrites) vk::UpdateDescriptorSets(m_ctx->m_dev, totalWrites, writes, 0, nullptr); - vk::CmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.cast()->bind()); + vk::CmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.cast()->bind(rPass)); if (m_descSets[b]) vk::CmdBindDescriptorSets(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_ctx->m_pipelinelayout, 0, 1, &m_descSets[b], 0, nullptr); @@ -2588,7 +2809,10 @@ struct VulkanCommandQueue : IGraphicsCommandQueue ThrowIfFailed(vk::CreateFence(m_ctx->m_dev, &fenceInfo, nullptr, &m_dynamicBufFence)); } - void startRenderer() {} + void startRenderer() + { + static_cast(m_parent->getDataFactory())->SetupGammaResources(); + } void stopRenderer() { @@ -2771,77 +2995,102 @@ struct VulkanCommandQueue : IGraphicsCommandQueue VkCommandBuffer cmdBuf = m_cmdBufs[m_drawBuf]; VulkanTextureR* csource = m_resolveDispSource.cast(); +#ifndef NDEBUG + if (!csource->m_colorBindCount) + Log.report(logvisor::Fatal, + "texture provided to resolveDisplay() must have at least 1 color binding"); +#endif ThrowIfFailed(vk::AcquireNextImageKHR(m_ctx->m_dev, sc.m_swapChain, UINT64_MAX, m_swapChainReadySem, nullptr, &sc.m_backBuf)); VulkanContext::Window::SwapChain::Buffer& dest = sc.m_bufs[sc.m_backBuf]; - SetImageLayout(cmdBuf, dest.m_image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, 1); - if (m_resolveDispSource == m_boundTarget) - SetImageLayout(cmdBuf, csource->m_colorTex, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1, 1); - - if (csource->m_samplesColor > 1) + VulkanDataFactoryImpl* dataFactory = static_cast(m_parent->getDataFactory()); + if (dataFactory->m_gamma != 1.f) { - VkImageResolve resolveInfo = {}; - resolveInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveInfo.srcSubresource.mipLevel = 0; - resolveInfo.srcSubresource.baseArrayLayer = 0; - resolveInfo.srcSubresource.layerCount = 1; - resolveInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - resolveInfo.dstSubresource.mipLevel = 0; - resolveInfo.dstSubresource.baseArrayLayer = 0; - resolveInfo.dstSubresource.layerCount = 1; - resolveInfo.extent.width = csource->m_width; - resolveInfo.extent.height = csource->m_height; - resolveInfo.extent.depth = 1; - vk::CmdResolveImage(cmdBuf, - csource->m_colorTex, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dest.m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, &resolveInfo); + SWindowRect rect(0, 0, csource->m_width, csource->m_height); + _resolveBindTexture(cmdBuf, csource, rect, true, 0, true, false); + VulkanShaderDataBinding* gammaBinding = dataFactory->m_gammaBinding.cast(); + + SetImageLayout(cmdBuf, dest.m_image, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, 1); + + vk::CmdBeginRenderPass(cmdBuf, &dest.m_passBeginInfo, VK_SUBPASS_CONTENTS_INLINE); + + gammaBinding->m_texs[0].tex = m_resolveDispSource.get(); + gammaBinding->bind(cmdBuf, m_drawBuf, m_ctx->m_passColorOnly); + vk::CmdDraw(cmdBuf, 4, 1, 0, 0); + gammaBinding->m_texs[0].tex.reset(); + + vk::CmdEndRenderPass(cmdBuf); + + SetImageLayout(cmdBuf, dest.m_image, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 1, 1); } else { - VkImageCopy copyInfo = {}; - copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyInfo.srcSubresource.mipLevel = 0; - copyInfo.srcSubresource.baseArrayLayer = 0; - copyInfo.srcSubresource.layerCount = 1; - copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - copyInfo.dstSubresource.mipLevel = 0; - copyInfo.dstSubresource.baseArrayLayer = 0; - copyInfo.dstSubresource.layerCount = 1; - copyInfo.extent.width = csource->m_width; - copyInfo.extent.height = csource->m_height; - copyInfo.extent.depth = 1; - vk::CmdCopyImage(cmdBuf, - csource->m_colorTex, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, - dest.m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, - 1, ©Info); + SetImageLayout(cmdBuf, dest.m_image, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, 1); + + if (m_resolveDispSource == m_boundTarget) + SetImageLayout(cmdBuf, csource->m_colorTex, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 1, 1); + + if (csource->m_samplesColor > 1) + { + VkImageResolve resolveInfo = {}; + resolveInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + resolveInfo.srcSubresource.mipLevel = 0; + resolveInfo.srcSubresource.baseArrayLayer = 0; + resolveInfo.srcSubresource.layerCount = 1; + resolveInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + resolveInfo.dstSubresource.mipLevel = 0; + resolveInfo.dstSubresource.baseArrayLayer = 0; + resolveInfo.dstSubresource.layerCount = 1; + resolveInfo.extent.width = csource->m_width; + resolveInfo.extent.height = csource->m_height; + resolveInfo.extent.depth = 1; + vk::CmdResolveImage(cmdBuf, + csource->m_colorTex, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dest.m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, &resolveInfo); + } + else + { + VkImageCopy copyInfo = {}; + copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyInfo.srcSubresource.mipLevel = 0; + copyInfo.srcSubresource.baseArrayLayer = 0; + copyInfo.srcSubresource.layerCount = 1; + copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + copyInfo.dstSubresource.mipLevel = 0; + copyInfo.dstSubresource.baseArrayLayer = 0; + copyInfo.dstSubresource.layerCount = 1; + copyInfo.extent.width = csource->m_width; + copyInfo.extent.height = csource->m_height; + copyInfo.extent.depth = 1; + vk::CmdCopyImage(cmdBuf, + csource->m_colorTex, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, + dest.m_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, + 1, ©Info); + } + + SetImageLayout(cmdBuf, dest.m_image, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 1, 1); + + if (m_resolveDispSource == m_boundTarget) + SetImageLayout(cmdBuf, csource->m_colorTex, VK_IMAGE_ASPECT_COLOR_BIT, + VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, 1); } - SetImageLayout(cmdBuf, dest.m_image, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 1, 1); - dest.m_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - if (m_resolveDispSource == m_boundTarget) - SetImageLayout(cmdBuf, csource->m_colorTex, VK_IMAGE_ASPECT_COLOR_BIT, - VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, 1, 1); - m_resolveDispSource.reset(); return true; } - void resolveBindTexture(const boo::ObjToken& texture, - const SWindowRect& rect, bool tlOrigin, - int bindIdx, bool color, bool depth, bool clearDepth) + void _resolveBindTexture(VkCommandBuffer cmdBuf, VulkanTextureR* ctexture, + const SWindowRect& rect, bool tlOrigin, + int bindIdx, bool color, bool depth) { - VkCommandBuffer cmdBuf = m_cmdBufs[m_fillBuf]; - VulkanTextureR* ctexture = texture.cast(); - - vk::CmdEndRenderPass(cmdBuf); - if (color && ctexture->m_colorBindCount) { if (ctexture->m_samplesColor <= 1) @@ -3013,7 +3262,17 @@ struct VulkanCommandQueue : IGraphicsCommandQueue ctexture->m_depthBindLayout[bindIdx] = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; } } + } + void resolveBindTexture(const boo::ObjToken& texture, + const SWindowRect& rect, bool tlOrigin, + int bindIdx, bool color, bool depth, bool clearDepth) + { + VkCommandBuffer cmdBuf = m_cmdBufs[m_fillBuf]; + VulkanTextureR* ctexture = texture.cast(); + + vk::CmdEndRenderPass(cmdBuf); + _resolveBindTexture(cmdBuf, ctexture, rect, tlOrigin, bindIdx, color, depth); vk::CmdBeginRenderPass(cmdBuf, &m_boundTarget.cast()->m_passBeginInfo, VK_SUBPASS_CONTENTS_INLINE); if (clearDepth) @@ -3232,81 +3491,7 @@ void VulkanTextureD::unmap() } VulkanDataFactoryImpl::VulkanDataFactoryImpl(IGraphicsContext* parent, VulkanContext* ctx) -: m_parent(parent), m_ctx(ctx) -{ - VkDescriptorSetLayoutBinding layoutBindings[BOO_GLSL_MAX_UNIFORM_COUNT + BOO_GLSL_MAX_TEXTURE_COUNT]; - for (int i=0 ; im_dev, &descriptorLayout, nullptr, - &ctx->m_descSetLayout)); - - VkPipelineLayoutCreateInfo pipelineLayout = {}; - pipelineLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayout.setLayoutCount = 1; - pipelineLayout.pSetLayouts = &ctx->m_descSetLayout; - ThrowIfFailed(vk::CreatePipelineLayout(ctx->m_dev, &pipelineLayout, nullptr, &ctx->m_pipelinelayout)); - - VkAttachmentDescription attachments[2] = {}; - - /* color attachment */ - attachments[0].format = ctx->m_displayFormat; - attachments[0].samples = VkSampleCountFlagBits(m_ctx->m_sampleCountColor); - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachments[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - attachments[0].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - VkAttachmentReference colorAttachmentRef = {0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}; - - /* depth attachment */ - attachments[1].format = VK_FORMAT_D32_SFLOAT; - attachments[1].samples = VkSampleCountFlagBits(m_ctx->m_sampleCountDepth); - attachments[1].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachments[1].storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachments[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachments[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - attachments[1].initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - attachments[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - VkAttachmentReference depthAttachmentRef = {1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL}; - - /* render subpass */ - VkSubpassDescription subpass = {}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - subpass.pDepthStencilAttachment = &depthAttachmentRef; - - /* render pass */ - VkRenderPassCreateInfo renderPass = {}; - renderPass.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPass.attachmentCount = 2; - renderPass.pAttachments = attachments; - renderPass.subpassCount = 1; - renderPass.pSubpasses = &subpass; - ThrowIfFailed(vk::CreateRenderPass(ctx->m_dev, &renderPass, nullptr, &ctx->m_pass)); -} +: m_parent(parent), m_ctx(ctx) {} static uint64_t CompileVert(std::vector& out, const char* vertSource, uint64_t srcKey, VulkanDataFactoryImpl& factory) diff --git a/lib/win/ApplicationWin32.cpp b/lib/win/ApplicationWin32.cpp index b5ab7c4..b9819fd 100644 --- a/lib/win/ApplicationWin32.cpp +++ b/lib/win/ApplicationWin32.cpp @@ -111,11 +111,9 @@ public: m_3dCtx.m_ctx11.m_sampleCount = samples; m_3dCtx.m_ctx11.m_anisotropy = anisotropy; m_3dCtx.m_ctx11.m_fbFormat = deepColor ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_R8G8B8A8_UNORM; - //m_3dCtx.m_ctx11.m_fbFormat = DXGI_FORMAT_R8G8B8A8_UNORM; m_3dCtx.m_ctx12.m_sampleCount = samples; m_3dCtx.m_ctx12.m_anisotropy = anisotropy; m_3dCtx.m_ctx12.RGBATex2DFBViewDesc.Format = deepColor ? DXGI_FORMAT_R16G16B16A16_FLOAT : DXGI_FORMAT_R8G8B8A8_UNORM; - //m_3dCtx.m_ctx12.RGBATex2DFBViewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; m_3dCtx.m_ctxOgl.m_glCtx.m_sampleCount = samples; m_3dCtx.m_ctxOgl.m_glCtx.m_anisotropy = anisotropy; m_3dCtx.m_ctxOgl.m_glCtx.m_deepColor = deepColor; diff --git a/lib/win/WinCommon.hpp b/lib/win/WinCommon.hpp index d66e3c2..8b8a4d7 100644 --- a/lib/win/WinCommon.hpp +++ b/lib/win/WinCommon.hpp @@ -39,6 +39,7 @@ struct D3D12Context struct Window { ComPtr m_swapChain; + std::unordered_map> m_rtvHeaps; UINT m_backBuf = 0; bool m_needsResize = false; size_t width, height; @@ -69,12 +70,32 @@ struct D3D11Context struct Window { ComPtr m_swapChain; + ComPtr m_swapChainTex; + ComPtr m_swapChainRTV; bool m_needsResize = false; size_t width, height; bool m_needsFSTransition = false; bool m_fs = false; DXGI_MODE_DESC m_fsdesc = {}; + + void clearRTV() + { + m_swapChainTex.Reset(); + m_swapChainRTV.Reset(); + } + + void setupRTV(ComPtr& sc, ID3D11Device* dev) + { + m_swapChain = sc; + m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &m_swapChainTex); + D3D11_TEXTURE2D_DESC resDesc; + m_swapChainTex->GetDesc(&resDesc); + width = resDesc.Width; + height = resDesc.Height; + CD3D11_RENDER_TARGET_VIEW_DESC rtvDesc(D3D11_RTV_DIMENSION_TEXTURE2D, resDesc.Format); + dev->CreateRenderTargetView(m_swapChainTex.Get(), &rtvDesc, &m_swapChainRTV); + } }; std::unordered_map m_windows; diff --git a/lib/win/WindowWin32.cpp b/lib/win/WindowWin32.cpp index 3f7f795..3e44540 100644 --- a/lib/win/WindowWin32.cpp +++ b/lib/win/WindowWin32.cpp @@ -98,6 +98,7 @@ public: ID3D12CommandQueue* cmdQueue; m_dataFactory = _NewD3D12DataFactory(&b3dCtx.m_ctx12, this); m_commandQueue = _NewD3D12CommandQueue(&b3dCtx.m_ctx12, &w, this, &cmdQueue); + m_commandQueue->startRenderer(); scDesc.Format = b3dCtx.m_ctx12.RGBATex2DFBViewDesc.Format; scDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; @@ -129,16 +130,11 @@ public: auto insIt = b3dCtx.m_ctx11.m_windows.emplace(std::make_pair(parentWindow, D3D11Context::Window())); D3D11Context::Window& w = insIt.first->second; + w.setupRTV(m_swapChain, b3dCtx.m_ctx11.m_dev.Get()); - m_swapChain.As(&w.m_swapChain); - ComPtr fbRes; - m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), &fbRes); - D3D11_TEXTURE2D_DESC resDesc; - fbRes->GetDesc(&resDesc); - w.width = resDesc.Width; - w.height = resDesc.Height; m_dataFactory = _NewD3D11DataFactory(&b3dCtx.m_ctx11, this); m_commandQueue = _NewD3D11CommandQueue(&b3dCtx.m_ctx11, &insIt.first->second, this); + m_commandQueue->startRenderer(); if (FAILED(m_swapChain->GetContainingOutput(&m_output))) Log.report(logvisor::Fatal, "unable to get DXGI output"); @@ -651,6 +647,7 @@ public: m_dataFactory = _NewVulkanDataFactory(this, m_ctx); m_commandQueue = _NewVulkanCommandQueue(m_ctx, m_ctx->m_windows[m_parentWindow].get(), this); + m_commandQueue->startRenderer(); return true; } diff --git a/logvisor b/logvisor index b89d18c..bb0535f 160000 --- a/logvisor +++ b/logvisor @@ -1 +1 @@ -Subproject commit b89d18c47181371c7871f49751f5d657f02f1fd6 +Subproject commit bb0535f3a9f4f0ac68af01dad11800db257bd7ab diff --git a/test/main.cpp b/test/main.cpp index 6febe7f..1896a87 100644 --- a/test/main.cpp +++ b/test/main.cpp @@ -201,7 +201,7 @@ struct CTestWindowCallback : IWindowCallback } void mouseMove(const SWindowCoord& coord) { - fprintf(stderr, "Mouse Move (%f,%f)\n", coord.norm[0], coord.norm[1]); + //fprintf(stderr, "Mouse Move (%f,%f)\n", coord.norm[0], coord.norm[1]); } void mouseEnter(const SWindowCoord &coord) { @@ -286,7 +286,7 @@ struct TestApplicationCallback : IApplicationCallback /* Create render target */ int x, y, w, h; self->mainWindow->getWindowFrame(x, y, w, h); - self->m_renderTarget = ctx.newRenderTexture(w, h, boo::TextureClampMode::Repeat, 1, 0); + self->m_renderTarget = ctx.newRenderTexture(w, h, boo::TextureClampMode::ClampToEdge, 1, 0); /* Make Tri-strip VBO */ struct Vert @@ -332,7 +332,7 @@ struct TestApplicationCallback : IApplicationCallback tex[i][j][3] = 0xff; } boo::ObjToken texture = ctx.newStaticTexture(256, 256, 1, TextureFormat::RGBA8, - boo::TextureClampMode::Repeat, tex, 256*256*4).get(); + boo::TextureClampMode::ClampToEdge, tex, 256*256*4).get(); /* Make shader pipeline */ boo::ObjToken pipeline; @@ -530,11 +530,9 @@ struct TestApplicationCallback : IApplicationCallback gfxQ->setScissor(r); //float rgba[] = {std::max(0.f, sinf(frameIdx / 60.0)), std::max(0.f, cosf(frameIdx / 60.0)), 0.0, 1.0}; float gammaT = sinf(frameIdx / 60.0) + 1.f; - //if (gammaT < 0.f) - // gammaT = 1.f / ((1.f - gammaT) * 2.f); - //else - // gammaT = gammaT + 1.f; - printf("%f\n", gammaT); + if (gammaT < 1.f) + gammaT = gammaT * 0.5f + 0.5f; + //printf("%f\n", gammaT); mainWindow->getDataFactory()->setDisplayGamma(gammaT); //gfxQ->setClearColor(rgba); gfxQ->clearTarget(); @@ -554,10 +552,9 @@ struct TestApplicationCallback : IApplicationCallback } } + gfxQ->stopRenderer(); m_renderTarget.reset(); m_binding.reset(); - - gfxQ->stopRenderer(); return 0; } void appQuitting(IApplication*) @@ -592,7 +589,7 @@ int main(int argc, const boo::SystemChar** argv) logvisor::RegisterConsoleLogger(); boo::TestApplicationCallback appCb; int ret = ApplicationRun(boo::IApplication::EPlatformType::Auto, - appCb, _S("boo"), _S("boo"), argc, argv, {}, 1, 1, false); + appCb, _S("boo"), _S("boo"), argc, argv, {}, 1, 1, true); printf("IM DYING!!\n"); return ret; }