mirror of https://github.com/AxioDL/boo.git
Gamma correction for Vulkan, D3D, OpenGL
This commit is contained in:
parent
2df85e8f8b
commit
93c787dcd4
2
glslang
2
glslang
|
@ -1 +1 @@
|
|||
Subproject commit 2edde6665d9a56ead5ea0e55b4e64d9a803e6164
|
||||
Subproject commit 82ead04c39c6a4b7fa153d692b26181091c43c15
|
|
@ -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<Buffer> m_bufs;
|
||||
uint32_t m_backBuf = 0;
|
||||
|
|
|
@ -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<ITextureS>
|
|||
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<ITextureSA>
|
|||
{
|
||||
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<ITextureD>
|
|||
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<IShaderPipeline>
|
|||
}
|
||||
|
||||
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<std::mutex> lk(self->m_initmt);
|
||||
}
|
||||
self->m_initcv.notify_one();
|
||||
while (self->m_running)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> 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<D3D11TextureR>();
|
||||
if (csource)
|
||||
{
|
||||
ComPtr<ID3D11Texture2D> 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<ITextureR>& 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<D3D11TextureR>();
|
||||
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<ITextureR>& texture, const SWindowRect& rect,
|
||||
bool tlOrigin, int bindIdx, bool color, bool depth, bool clearDepth)
|
||||
{
|
||||
const D3D11TextureR* tex = texture.cast<D3D11TextureR>();
|
||||
_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<uint64_t, std::unique_ptr<D3D11ShareableShader>> m_sharedShaders;
|
||||
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
|
||||
|
||||
float m_gamma = 1.f;
|
||||
ObjToken<IShaderPipeline> m_gammaShader;
|
||||
ObjToken<ITextureD> m_gammaLUT;
|
||||
ObjToken<IGraphicsBufferS> m_gammaVBO;
|
||||
ObjToken<IVertexFormat> m_gammaVFMT;
|
||||
ObjToken<IShaderDataBinding> 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<Context&>(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<ITexture> 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<std::mutex> lk(self->m_initmt);
|
||||
}
|
||||
self->m_initcv.notify_one();
|
||||
D3D11DataFactory* dataFactory = static_cast<D3D11DataFactory*>(self->m_parent->getDataFactory());
|
||||
while (self->m_running)
|
||||
{
|
||||
{
|
||||
std::unique_lock<std::mutex> 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<D3D11TextureR>())
|
||||
{
|
||||
#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<D3D11ShaderDataBinding>();
|
||||
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<ID3D11Texture2D> 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<D3D11DataFactory*>(m_parent->getDataFactory())->SetupGammaResources();
|
||||
}
|
||||
|
||||
void D3D11CommandQueue::execute()
|
||||
{
|
||||
/* Finish command list */
|
||||
|
|
|
@ -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<ITextureS>
|
|||
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<ITextureSA>
|
|||
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<ITextureD>
|
|||
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<ITextureR>
|
|||
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<IShaderPipeline>
|
|||
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<ITextureR>& source)
|
||||
{
|
||||
D3D12TextureR* csource = source.cast<D3D12TextureR>();
|
||||
|
||||
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<ID3D12Resource> 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<ITextureR>& source);
|
||||
|
||||
UINT64 m_submittedFenceVal = 0;
|
||||
void execute();
|
||||
|
@ -1667,6 +1650,43 @@ class D3D12DataFactory : public ID3DDataFactory, public GraphicsDataFactoryHead
|
|||
std::unordered_map<uint64_t, std::unique_ptr<D3D12ShareableShader>> m_sharedShaders;
|
||||
std::unordered_map<uint64_t, uint64_t> m_sourceToBinary;
|
||||
|
||||
float m_gamma = 1.f;
|
||||
ObjToken<IShaderPipeline> m_gammaShader;
|
||||
ObjToken<ITextureD> m_gammaLUT;
|
||||
ObjToken<IGraphicsBufferS> m_gammaVBO;
|
||||
ObjToken<IVertexFormat> m_gammaVFMT;
|
||||
ObjToken<IShaderDataBinding> 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<Context&>(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<ITexture> 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<D3D12DataFactory*>(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<D3D12DataFactory*>(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<ITextureR>& source)
|
||||
{
|
||||
D3D12TextureR* csource = source.cast<D3D12TextureR>();
|
||||
#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<ID3D12Resource> 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<D3D12DataFactory*>(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<ID3D12DescriptorHeap> 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<D3D12ShaderDataBinding>();
|
||||
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)
|
||||
|
|
|
@ -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<uint64_t, std::unique_ptr<GLShareableShader>> m_sharedShaders;
|
||||
|
||||
float m_gamma = 1.f;
|
||||
ObjToken<IShaderPipeline> m_gammaShader;
|
||||
ObjToken<ITextureD> m_gammaLUT;
|
||||
ObjToken<IGraphicsBufferS> 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<IGraphicsBufferD> 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<GLTextureR>())
|
||||
{
|
||||
#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<GLShaderPipeline>()->bind();
|
||||
dataFactory->m_gammaVFMT.cast<GLVertexFormat>()->bind(self->m_drawBuf);
|
||||
dataFactory->m_gammaLUT.cast<GLTextureD>()->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<GLShaderPipeline>()->bind();
|
||||
dataFactory->m_gammaVFMT.cast<GLVertexFormat>()->bind(self->m_drawBuf);
|
||||
dataFactory->m_gammaLUT.cast<GLTextureD>()->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;
|
||||
|
|
|
@ -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<uint64_t, std::unique_ptr<VulkanShareableShader>> m_sharedShaders;
|
||||
std::vector<int> m_texUnis;
|
||||
|
||||
float m_gamma = 1.f;
|
||||
ObjToken<IShaderPipeline> m_gammaShader;
|
||||
ObjToken<ITextureD> m_gammaLUT;
|
||||
ObjToken<IGraphicsBufferS> m_gammaVBO;
|
||||
ObjToken<IVertexFormat> m_gammaVFMT;
|
||||
ObjToken<IShaderDataBinding> 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<Context&>(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<ITexture> 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<uint64_t, uint64_t> 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<BOO_GLSL_MAX_UNIFORM_COUNT ; ++i)
|
||||
{
|
||||
layoutBindings[i].binding = i;
|
||||
layoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
layoutBindings[i].descriptorCount = 1;
|
||||
layoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
layoutBindings[i].pImmutableSamplers = nullptr;
|
||||
}
|
||||
for (int i=BOO_GLSL_MAX_UNIFORM_COUNT ; i<BOO_GLSL_MAX_UNIFORM_COUNT+BOO_GLSL_MAX_TEXTURE_COUNT ; ++i)
|
||||
{
|
||||
layoutBindings[i].binding = i;
|
||||
layoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
layoutBindings[i].descriptorCount = 1;
|
||||
layoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
layoutBindings[i].pImmutableSamplers = nullptr;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descriptorLayout = {};
|
||||
descriptorLayout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
descriptorLayout.pNext = nullptr;
|
||||
descriptorLayout.bindingCount = BOO_GLSL_MAX_UNIFORM_COUNT + BOO_GLSL_MAX_TEXTURE_COUNT;
|
||||
descriptorLayout.pBindings = layoutBindings;
|
||||
|
||||
ThrowIfFailed(vk::CreateDescriptorSetLayout(m_dev, &descriptorLayout, nullptr,
|
||||
&m_descSetLayout));
|
||||
|
||||
VkPipelineLayoutCreateInfo pipelineLayout = {};
|
||||
pipelineLayout.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
pipelineLayout.setLayoutCount = 1;
|
||||
pipelineLayout.pSetLayouts = &m_descSetLayout;
|
||||
ThrowIfFailed(vk::CreatePipelineLayout(m_dev, &pipelineLayout, nullptr, &m_pipelinelayout));
|
||||
|
||||
VkAttachmentDescription attachments[2] = {};
|
||||
|
||||
/* color attachment */
|
||||
attachments[0].format = m_displayFormat;
|
||||
attachments[0].samples = VkSampleCountFlagBits(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_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(m_dev, &renderPass, nullptr, &m_pass));
|
||||
|
||||
/* render pass color only */
|
||||
renderPass.attachmentCount = 1;
|
||||
subpass.pDepthStencilAttachment = nullptr;
|
||||
ThrowIfFailed(vk::CreateRenderPass(m_dev, &renderPass, nullptr, &m_passColorOnly));
|
||||
|
||||
/* images */
|
||||
sc.m_bufs.resize(swapchainImageCount);
|
||||
for (uint32_t i=0 ; i<swapchainImageCount ; ++i)
|
||||
{
|
||||
Window::SwapChain::Buffer& buf = sc.m_bufs[i];
|
||||
buf.m_image = swapchainImages[i];
|
||||
buf.setImage(this, swapchainImages[i], swapChainExtent.width, swapChainExtent.height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -708,7 +916,7 @@ bool VulkanContext::_resizeSwapChains()
|
|||
swapChainInfo.oldSwapchain = oldSc.m_swapChain;
|
||||
swapChainInfo.clipped = true;
|
||||
swapChainInfo.imageColorSpace = resize.m_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;
|
||||
|
@ -730,7 +938,7 @@ bool VulkanContext::_resizeSwapChains()
|
|||
for (uint32_t i=0 ; i<swapchainImageCount ; ++i)
|
||||
{
|
||||
Window::SwapChain::Buffer& buf = sc.m_bufs[i];
|
||||
buf.m_image = swapchainImages[i];
|
||||
buf.setImage(this, swapchainImages[i], swapChainExtent.width, swapChainExtent.height);
|
||||
}
|
||||
|
||||
m_deferredResizes.pop();
|
||||
|
@ -995,6 +1203,10 @@ class VulkanTextureS : public GraphicsDataNode<ITextureS>
|
|||
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<ITextureSA>
|
|||
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<ITextureD>
|
|||
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<ITextureR>
|
|||
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<ITextureR>
|
|||
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<ITextureR>
|
|||
|
||||
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<IShaderDataBinding>
|
|||
#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<IShaderDataBinding>
|
|||
if (totalWrites)
|
||||
vk::UpdateDescriptorSets(m_ctx->m_dev, totalWrites, writes, 0, nullptr);
|
||||
|
||||
vk::CmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.cast<VulkanShaderPipeline>()->bind());
|
||||
vk::CmdBindPipeline(cmdBuf, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline.cast<VulkanShaderPipeline>()->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<VulkanDataFactoryImpl*>(m_parent->getDataFactory())->SetupGammaResources();
|
||||
}
|
||||
|
||||
void stopRenderer()
|
||||
{
|
||||
|
@ -2771,77 +2995,102 @@ struct VulkanCommandQueue : IGraphicsCommandQueue
|
|||
|
||||
VkCommandBuffer cmdBuf = m_cmdBufs[m_drawBuf];
|
||||
VulkanTextureR* csource = m_resolveDispSource.cast<VulkanTextureR>();
|
||||
#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<VulkanDataFactoryImpl*>(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<VulkanShaderDataBinding>();
|
||||
|
||||
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<ITextureR>& 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<VulkanTextureR>();
|
||||
|
||||
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<ITextureR>& texture,
|
||||
const SWindowRect& rect, bool tlOrigin,
|
||||
int bindIdx, bool color, bool depth, bool clearDepth)
|
||||
{
|
||||
VkCommandBuffer cmdBuf = m_cmdBufs[m_fillBuf];
|
||||
VulkanTextureR* ctexture = texture.cast<VulkanTextureR>();
|
||||
|
||||
vk::CmdEndRenderPass(cmdBuf);
|
||||
_resolveBindTexture(cmdBuf, ctexture, rect, tlOrigin, bindIdx, color, depth);
|
||||
vk::CmdBeginRenderPass(cmdBuf, &m_boundTarget.cast<VulkanTextureR>()->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 ; i<BOO_GLSL_MAX_UNIFORM_COUNT ; ++i)
|
||||
{
|
||||
layoutBindings[i].binding = i;
|
||||
layoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
layoutBindings[i].descriptorCount = 1;
|
||||
layoutBindings[i].stageFlags = VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
layoutBindings[i].pImmutableSamplers = nullptr;
|
||||
}
|
||||
for (int i=BOO_GLSL_MAX_UNIFORM_COUNT ; i<BOO_GLSL_MAX_UNIFORM_COUNT+BOO_GLSL_MAX_TEXTURE_COUNT ; ++i)
|
||||
{
|
||||
layoutBindings[i].binding = i;
|
||||
layoutBindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
layoutBindings[i].descriptorCount = 1;
|
||||
layoutBindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
layoutBindings[i].pImmutableSamplers = nullptr;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayoutCreateInfo descriptorLayout = {};
|
||||
descriptorLayout.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
descriptorLayout.pNext = nullptr;
|
||||
descriptorLayout.bindingCount = BOO_GLSL_MAX_UNIFORM_COUNT + BOO_GLSL_MAX_TEXTURE_COUNT;
|
||||
descriptorLayout.pBindings = layoutBindings;
|
||||
|
||||
ThrowIfFailed(vk::CreateDescriptorSetLayout(ctx->m_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<unsigned int>& out, const char* vertSource, uint64_t srcKey,
|
||||
VulkanDataFactoryImpl& factory)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -39,6 +39,7 @@ struct D3D12Context
|
|||
struct Window
|
||||
{
|
||||
ComPtr<IDXGISwapChain3> m_swapChain;
|
||||
std::unordered_map<ID3D12Resource*, ComPtr<ID3D12DescriptorHeap>> m_rtvHeaps;
|
||||
UINT m_backBuf = 0;
|
||||
bool m_needsResize = false;
|
||||
size_t width, height;
|
||||
|
@ -69,12 +70,32 @@ struct D3D11Context
|
|||
struct Window
|
||||
{
|
||||
ComPtr<IDXGISwapChain1> m_swapChain;
|
||||
ComPtr<ID3D11Texture2D> m_swapChainTex;
|
||||
ComPtr<ID3D11RenderTargetView> 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<IDXGISwapChain1>& 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<const boo::IWindow*, Window> m_windows;
|
||||
|
||||
|
|
|
@ -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<IDXGISwapChain1>(&w.m_swapChain);
|
||||
ComPtr<ID3D11Texture2D> 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;
|
||||
}
|
||||
|
||||
|
|
2
logvisor
2
logvisor
|
@ -1 +1 @@
|
|||
Subproject commit b89d18c47181371c7871f49751f5d657f02f1fd6
|
||||
Subproject commit bb0535f3a9f4f0ac68af01dad11800db257bd7ab
|
|
@ -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<ITexture> 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<IShaderPipeline> 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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue