Test different variations of DXGI swapchains on D3D11 and D3D12

This commit is contained in:
baldurk committed 2020-10-02 17:41:58 +01:00
1 parent 4518fda3ed
commit 9e17b91a94
11 files changed
+370 -8

No files matched your search

@@ -0,0 +1,156 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2020 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "../win32/win32_window.h"
#include "d3d11_test.h"
RD_TEST(D3D11_Swapchain_Zoo, D3D11GraphicsTest)
{
static constexpr const char *Description = "Tests all types of swapchain that D3D11 supports.";
int main()
{
// initialise, create window, create device, etc
if(!Init())
return 3;
DXGI_SWAP_CHAIN_DESC swapDesc;
ZeroMemory(&swapDesc, sizeof(swapDesc));
swapDesc.BufferCount = backbufferCount;
swapDesc.BufferDesc.Width = screenWidth;
swapDesc.BufferDesc.Height = screenHeight;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
swapDesc.SampleDesc.Quality = 0;
swapDesc.Windowed = TRUE;
swapDesc.Flags = 0;
std::vector<Win32Window *> wins;
std::vector<IDXGISwapChainPtr> swaps;
std::vector<ID3D11RenderTargetViewPtr> bbs;
std::vector<std::string> names;
auto addWindow = [&](std::string name) {
wins.push_back(new Win32Window(screenWidth, screenHeight, screenTitle));
swaps.push_back({});
bbs.push_back({});
names.push_back(name);
swapDesc.OutputWindow = wins.back()->wnd;
fact->CreateSwapChain(dev, &swapDesc, &swaps.back());
ID3D11Texture2DPtr bb;
CHECK_HR(swaps.back()->GetBuffer(0, __uuidof(ID3D11Texture2D), (void **)&bb));
CHECK_HR(dev->CreateRenderTargetView(bb, NULL, &bbs.back()));
};
// always support sequential flip
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapDesc.SampleDesc.Count = 1;
addWindow("SEQUENTIAL");
// ditto MSAA
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapDesc.SampleDesc.Count = 4;
addWindow("MSAA RGBA8");
// ditto FP16 (on feature level 10 and above)
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
swapDesc.SampleDesc.Count = 1;
addWindow("RGBA16");
// check FP16 and MSAA
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R16G16B16A16_FLOAT;
swapDesc.SampleDesc.Count = 4;
addWindow("MSAA RGBA16");
IDXGIFactory4Ptr factory4 = fact;
if(factory4)
{
// only test flip effects if we can get factory4, which is windows 10 only.
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapDesc.SampleDesc.Count = 1;
addWindow("FLIP_DISCARD");
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapDesc.SampleDesc.Count = 1;
addWindow("FLIP_SEQUENTIAL");
}
ID3DBlobPtr vsblob = Compile(D3DDefaultVertex, "main", "vs_4_0");
ID3DBlobPtr psblob = Compile(D3DDefaultPixel, "main", "ps_4_0");
CreateDefaultInputLayout(vsblob);
ID3D11VertexShaderPtr vs = CreateVS(vsblob);
ID3D11PixelShaderPtr ps = CreatePS(psblob);
ID3D11BufferPtr vb = MakeBuffer().Vertex().Data(DefaultTri);
while(Running())
{
for(Win32Window *win : wins)
win->Update();
ClearRenderTargetView(bbRTV, {0.0f, 0.0f, 0.0f, 1.0f});
IASetVertexBuffer(vb, sizeof(DefaultA2V), 0);
ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->IASetInputLayout(defaultLayout);
ctx->VSSetShader(vs, NULL, 0);
ctx->PSSetShader(ps, NULL, 0);
RSSetViewport({0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f});
ctx->OMSetRenderTargets(1, &bbRTV.GetInterfacePtr(), NULL);
ctx->Draw(3, 0);
for(size_t i = 0; i < bbs.size(); i++)
{
ID3D11RenderTargetViewPtr bb = bbs[i];
setMarker(names[i]);
ctx->OMSetRenderTargets(1, &bb.GetInterfacePtr(), NULL);
ClearRenderTargetView(bb, {0.0f, 0.0f, 0.0f, 1.0f});
ctx->Draw(3, 0);
}
Present();
for(IDXGISwapChainPtr s : swaps)
s->Present(0, 0);
}
return 0;
}
};
REGISTER_TEST();
+7 -3
View File
@@ -37,7 +37,7 @@ namespace
HMODULE d3d11 = NULL;
HMODULE dxgi = NULL;
HMODULE d3dcompiler = NULL;
IDXGIFactoryPtr factory;
IDXGIFactory1Ptr factory;
std::vector<IDXGIAdapterPtr> adapters;
bool warp = false;
@@ -74,7 +74,9 @@ void D3D11GraphicsTest::Prepare(int argc, char **argv)
PFN_CREATE_DXGI_FACTORY createFactory = NULL;
if(dxgi)
createFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(dxgi, "CreateDXGIFactory");
{
createFactory = (PFN_CREATE_DXGI_FACTORY)GetProcAddress(dxgi, "CreateDXGIFactory1");
}
if(d3d11 && d3dcompiler)
{
@@ -91,7 +93,7 @@ void D3D11GraphicsTest::Prepare(int argc, char **argv)
if(createFactory)
{
hr = createFactory(__uuidof(IDXGIFactory), (void **)&factory);
hr = createFactory(__uuidof(IDXGIFactory1), (void **)&factory);
if(SUCCEEDED(hr))
adapters = FindD3DAdapters(factory, argc, argv, warp);
@@ -314,6 +316,8 @@ void D3D11GraphicsTest::PostDeviceCreate()
ctx3 = ctx;
ctx4 = ctx;
fact = factory;
annot = ctx;
std::string blitPixel = R"EOSHADER(
+1
View File
@@ -181,6 +181,7 @@ struct D3D11GraphicsTest : public GraphicsTest
GraphicsWindow *mainWindow = NULL;
IDXGIFactory1Ptr fact;
IDXGISwapChainPtr swap;
ID3D11InputLayoutPtr defaultLayout;
@@ -0,0 +1,147 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2020 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "../win32/win32_window.h"
#include "d3d12_test.h"
RD_TEST(D3D12_Swapchain_Zoo, D3D12GraphicsTest)
{
static constexpr const char *Description = "Tests both types of swapchain that D3D12 supports.";
void Prepare(int argc, char **argv)
{
D3D12GraphicsTest::Prepare(argc, argv);
if(m_12On7)
Avail = "True swapchains not supportedd on D3D12On7";
}
int main()
{
// initialise, create window, create device, etc
if(!Init())
return 3;
IDXGIFactory4Ptr factory4 = m_Factory;
DXGI_SWAP_CHAIN_DESC1 swapDesc = {};
swapDesc.BufferCount = 2;
swapDesc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT;
swapDesc.Flags = 0;
swapDesc.Format = backbufferFmt;
swapDesc.Width = screenWidth;
swapDesc.Height = screenHeight;
swapDesc.SampleDesc.Count = 1;
swapDesc.SampleDesc.Quality = 0;
swapDesc.Scaling = DXGI_SCALING_STRETCH;
swapDesc.Stereo = FALSE;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
// make second window
Win32Window *window2 = new Win32Window(screenWidth, screenHeight, screenTitle);
IDXGISwapChain1Ptr window2Swap;
// make sequential swapchain with normal format
swapDesc.Format = backbufferFmt;
swapDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
CHECK_HR(
factory4->CreateSwapChainForHwnd(queue, window2->wnd, &swapDesc, NULL, NULL, &window2Swap));
ID3D12ResourcePtr window2Tex[2];
CHECK_HR(window2Swap->GetBuffer(0, __uuidof(ID3D12Resource), (void **)&window2Tex[0]));
CHECK_HR(window2Swap->GetBuffer(1, __uuidof(ID3D12Resource), (void **)&window2Tex[1]));
ID3DBlobPtr vsblob = Compile(D3DDefaultVertex, "main", "vs_4_0");
ID3DBlobPtr psblob = Compile(D3DDefaultPixel, "main", "ps_4_0");
ID3D12ResourcePtr vb = MakeBuffer().Data(DefaultTri);
ID3D12RootSignaturePtr sig = MakeSig({});
ID3D12PipelineStatePtr pso = MakePSO().RootSig(sig).InputLayout().VS(vsblob).PS(psblob);
ResourceBarrier(vb, D3D12_RESOURCE_STATE_COMMON, D3D12_RESOURCE_STATE_VERTEX_AND_CONSTANT_BUFFER);
while(Running())
{
window2->Update();
D3D12_CPU_DESCRIPTOR_HANDLE rtv;
ID3D12GraphicsCommandListPtr cmd = GetCommandBuffer();
Reset(cmd);
ResourceBarrier(cmd, window2Tex[texIdx], D3D12_RESOURCE_STATE_PRESENT,
D3D12_RESOURCE_STATE_RENDER_TARGET);
ID3D12ResourcePtr bb = StartUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET);
rtv = MakeRTV(bb).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(0);
ClearRenderTargetView(cmd, rtv, {0.0f, 0.0f, 0.0f, 1.0f});
cmd->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
IASetVertexBuffer(cmd, vb, sizeof(DefaultA2V), 0);
cmd->SetPipelineState(pso);
cmd->SetGraphicsRootSignature(sig);
RSSetViewport(cmd, {0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f});
RSSetScissorRect(cmd, {0, 0, screenWidth, screenHeight});
OMSetRenderTargets(cmd, {rtv}, {});
setMarker(cmd, "Draw 1");
cmd->DrawInstanced(3, 1, 0, 0);
rtv = MakeRTV(window2Tex[texIdx]).Format(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).CreateCPU(0);
ClearRenderTargetView(cmd, rtv, {0.0f, 0.0f, 0.0f, 1.0f});
OMSetRenderTargets(cmd, {rtv}, {});
setMarker(cmd, "Draw 2");
cmd->DrawInstanced(3, 1, 0, 0);
ResourceBarrier(cmd, window2Tex[texIdx], D3D12_RESOURCE_STATE_RENDER_TARGET,
D3D12_RESOURCE_STATE_PRESENT);
FinishUsingBackbuffer(cmd, D3D12_RESOURCE_STATE_RENDER_TARGET);
cmd->Close();
Submit({cmd});
Present();
window2Swap->Present(0, 0);
}
delete window2;
return 0;
}
};
REGISTER_TEST();
+2
View File
@@ -164,6 +164,7 @@
<ClCompile Include="d3d11\d3d11_structured_buffer_misaligned_dirty.cpp" />
<ClCompile Include="d3d11\d3d11_structured_buffer_nested.cpp" />
<ClCompile Include="d3d11\d3d11_structured_buffer_read.cpp" />
<ClCompile Include="d3d11\d3d11_swapchain_zoo.cpp" />
<ClCompile Include="d3d11\d3d11_test.cpp" />
<ClCompile Include="d3d11\d3d11_texture_3d.cpp" />
<ClCompile Include="d3d11\d3d11_texture_zoo.cpp" />
@@ -195,6 +196,7 @@
<ClCompile Include="d3d12\d3d12_sharing.cpp" />
<ClCompile Include="d3d12\d3d12_simple_dispatch.cpp" />
<ClCompile Include="d3d12\d3d12_simple_triangle.cpp" />
<ClCompile Include="d3d12\d3d12_swapchain_zoo.cpp" />
<ClCompile Include="d3d12\d3d12_test.cpp" />
<ClCompile Include="d3d12\d3d12_texture_zoo.cpp" />
<ClCompile Include="d3d12\d3d12_untyped_backbuffer_descriptor.cpp" />
+6
View File
@@ -544,6 +544,12 @@
<ClCompile Include="vk\vk_descriptor_variable_count.cpp">
<Filter>Vulkan\demos</Filter>
</ClCompile>
<ClCompile Include="d3d12\d3d12_swapchain_zoo.cpp">
<Filter>D3D12\demos</Filter>
</ClCompile>
<ClCompile Include="d3d11\d3d11_swapchain_zoo.cpp">
<Filter>D3D11\demos</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<Filter Include="D3D11">
+2
View File
@@ -37,6 +37,8 @@ extern std::string D3DDefaultPixel;
COM_SMARTPTR(IDXGISwapChain);
COM_SMARTPTR(IDXGISwapChain1);
COM_SMARTPTR(IDXGISwapChain2);
COM_SMARTPTR(IDXGISwapChain3);
COM_SMARTPTR(IDXGIFactory);
COM_SMARTPTR(IDXGIFactory1);
COM_SMARTPTR(IDXGIFactory4);
+4 -3
View File
@@ -150,7 +150,7 @@ def run_executable(exe: str, cmdline: str,
return res.ident
def run_and_capture(exe: str, cmdline: str, frame: int, *, capture_name=None, opts=rd.GetDefaultCaptureOptions(),
def run_and_capture(exe: str, cmdline: str, frame: int, *, frame_count=1, capture_name=None, opts=rd.GetDefaultCaptureOptions(),
timeout=None, logfile=None):
"""
Helper function to run an executable with a command line, capture a particular frame, and exit.
@@ -161,6 +161,7 @@ def run_and_capture(exe: str, cmdline: str, frame: int, *, capture_name=None, op
:param exe: The executable to run.
:param cmdline: The command line to pass.
:param frame: The frame to capture.
:param frame_count: The number of frames to capture.
:param capture_name: The name to use creating the captures
:param opts: The capture options to use
:param timeout: The timeout to wait before killing the process if no capture has happened.
@@ -174,10 +175,10 @@ def run_and_capture(exe: str, cmdline: str, frame: int, *, capture_name=None, op
control = TargetControl(run_executable(exe, cmdline, cappath=util.get_tmp_path(capture_name), opts=opts), timeout=timeout)
log.print("Queuing capture of frame {} with timeout of {}".format(frame, "default" if timeout is None else timeout))
log.print("Queuing capture of frame {}..{} with timeout of {}".format(frame, frame+frame_count, "default" if timeout is None else timeout))
# Capture frame
control.queue_capture(frame)
control.queue_capture(frame, frame_count)
# By default, runs until the first capture is made
control.run()
+3 -2
View File
@@ -134,6 +134,7 @@ class TestCase:
internal = False
demos_test_name = ''
demos_frame_cap = 5
demos_frame_count = 1
_test_list = {}
@staticmethod
@@ -203,8 +204,8 @@ class TestCase:
if self.demos_test_name != '':
logfile = os.path.join(util.get_tmp_dir(), 'demos.log')
return capture.run_and_capture(util.get_demos_binary(), self.demos_test_name + " --log " + logfile,
self.demos_frame_cap, logfile=logfile, opts=self.get_capture_options(),
timeout=util.get_demos_timeout())
self.demos_frame_cap, frame_count=self.demos_frame_count, logfile=logfile,
opts=self.get_capture_options(), timeout=util.get_demos_timeout())
raise NotImplementedError("If run() is not implemented in a test, then"
"get_capture() and check_capture() must be.")
@@ -0,0 +1,20 @@
import renderdoc as rd
import rdtest
class D3D11_Swapchain_Zoo(rdtest.TestCase):
demos_test_name = 'D3D11_Swapchain_Zoo'
demos_frame_cap = 50
demos_frame_count = 10
def check_capture(self):
draw = self.find_draw("DrawIndexed")
while draw is not None:
self.controller.SetFrameEvent(draw.eventId, False)
self.check_triangle(back=[0.0, 0.0, 0.0, 1.0])
rdtest.log.success("OK at {}".format(draw.previous.name))
draw = self.find_draw("DrawIndexed", draw.eventId+1)
@@ -0,0 +1,22 @@
import renderdoc as rd
import rdtest
class D3D12_Swapchain_Zoo(rdtest.TestCase):
demos_test_name = 'D3D12_Swapchain_Zoo'
def check_capture(self):
draw1 = self.find_draw("Draw 1")
draw2 = self.find_draw("Draw 2")
self.controller.SetFrameEvent(draw1.next.eventId, False)
self.check_triangle(back=[0.0, 0.0, 0.0, 1.0])
rdtest.log.success("Triangle in first draw (on first window) is OK")
self.controller.SetFrameEvent(draw2.next.eventId, False)
self.check_triangle(back=[0.0, 0.0, 0.0, 1.0])
rdtest.log.success("Triangle in second draw (on second window) is OK")