From 88189e316f0d44e37088ebb6b1ef918509fe002f Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 12 Jun 2019 19:07:22 +0100 Subject: [PATCH] End stream-out queries in ClearState(). Closes #1412 * Also add tests of stream-out and DrawAuto() --- renderdoc/driver/d3d11/d3d11_context_wrap.cpp | 28 ++++++++ ...d11_streamout.cpp => d3d11_stream_out.cpp} | 65 ++++++++++++++++++- util/test/demos/demos.vcxproj | 2 +- util/test/demos/demos.vcxproj.filters | 6 +- util/test/tests/D3D11/D3D11_Stream_Out.py | 58 +++++++++++++++++ 5 files changed, 153 insertions(+), 6 deletions(-) rename util/test/demos/d3d11/{d3d11_streamout.cpp => d3d11_stream_out.cpp} (63%) create mode 100644 util/test/tests/D3D11/D3D11_Stream_Out.py diff --git a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp index 6455771da..a9fe7c7b0 100644 --- a/renderdoc/driver/d3d11/d3d11_context_wrap.cpp +++ b/renderdoc/driver/d3d11/d3d11_context_wrap.cpp @@ -6427,6 +6427,20 @@ bool WrappedID3D11DeviceContext::Serialise_ClearState(SerialiserType &ser) { if(IsReplayingAndReading()) { + // end stream-out queries for outgoing targets + for(UINT b = 0; b < D3D11_SO_STREAM_COUNT; b++) + { + ID3D11Buffer *buf = m_CurrentPipelineState->SO.Buffers[b]; + + if(buf) + { + ResourceId id = GetIDForResource(buf); + + m_pRealContext->End(m_StreamOutCounters[id].query); + m_StreamOutCounters[id].running = false; + } + } + m_CurrentPipelineState->Clear(); m_pRealContext->ClearState(); VerifyState(); @@ -6454,6 +6468,20 @@ void WrappedID3D11DeviceContext::ClearState() m_ContextRecord->AddChunk(scope.Get()); } + // end stream-out queries for outgoing targets + for(UINT b = 0; b < D3D11_SO_STREAM_COUNT; b++) + { + ID3D11Buffer *buf = m_CurrentPipelineState->SO.Buffers[b]; + + if(buf) + { + ResourceId id = GetIDForResource(buf); + + m_pRealContext->End(m_StreamOutCounters[id].query); + m_StreamOutCounters[id].running = false; + } + } + m_CurrentPipelineState->Clear(); VerifyState(); } diff --git a/util/test/demos/d3d11/d3d11_streamout.cpp b/util/test/demos/d3d11/d3d11_stream_out.cpp similarity index 63% rename from util/test/demos/d3d11/d3d11_streamout.cpp rename to util/test/demos/d3d11/d3d11_stream_out.cpp index a35dfd101..f3de3db91 100644 --- a/util/test/demos/d3d11/d3d11_streamout.cpp +++ b/util/test/demos/d3d11/d3d11_stream_out.cpp @@ -24,7 +24,7 @@ #include "d3d11_test.h" -TEST(D3D11_StreamOut, D3D11GraphicsTest) +TEST(D3D11_Stream_Out, D3D11GraphicsTest) { static constexpr const char *Description = "Test using D3D11's streamout feature"; @@ -74,9 +74,25 @@ TEST(D3D11_StreamOut, D3D11GraphicsTest) ID3D11BufferPtr vb = MakeBuffer().Vertex().Data(DefaultTri); ID3D11BufferPtr so[2] = { - MakeBuffer().StreamOut().Size(2048), MakeBuffer().StreamOut().Size(2048), + MakeBuffer().StreamOut().Vertex().Size(2048), MakeBuffer().StreamOut().Vertex().Size(2048), }; + D3D11_INPUT_ELEMENT_DESC layoutdesc[] = { + { + "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0, + }, + { + "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 1, 0, D3D11_INPUT_PER_VERTEX_DATA, 0, + }, + { + "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0, + }, + }; + + ID3D11InputLayoutPtr streamoutLayout; + CHECK_HR(dev->CreateInputLayout(layoutdesc, ARRAY_COUNT(layoutdesc), vsblob->GetBufferPointer(), + vsblob->GetBufferSize(), &streamoutLayout)); + while(Running()) { ctx->ClearState(); @@ -124,6 +140,51 @@ TEST(D3D11_StreamOut, D3D11GraphicsTest) ctx->Draw(3, 0); + ctx->UpdateSubresource(so[0], 0, NULL, empty, 2048, 2048); + ctx->UpdateSubresource(so[1], 0, NULL, empty, 2048, 2048); + + // test DrawAuto() + + RSSetViewport({0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f}); + + // draw with streamout and explicitly unbind + ctx->SOSetTargets(2, bufs, offs); + ctx->Draw(3, 0); + ctx->SOSetTargets(0, NULL, NULL); + + RSSetViewport({0.0f, 0.0f, (float)screenWidth / 4.0f, (float)screenHeight / 4.0f, 0.0f, 1.0f}); + + ctx->IASetVertexBuffers(0, 2, bufs, &strides[0], offs); + ctx->IASetInputLayout(streamoutLayout); + ctx->DrawAuto(); + + RSSetViewport({0.0f, 0.0f, (float)screenWidth, (float)screenHeight, 0.0f, 1.0f}); + + ID3D11Buffer *emptyBuf[2] = {}; + ctx->IASetVertexBuffers(0, 2, emptyBuf, &strides[0], offs); + IASetVertexBuffer(vb, sizeof(DefaultA2V), 0); + ctx->IASetInputLayout(defaultLayout); + + // draw with streamout and clear state + ctx->SOSetTargets(2, bufs, offs); + ctx->DrawInstanced(3, 2, 0, 0); + ctx->ClearState(); + + ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + ctx->VSSetShader(vs, NULL, 0); + ctx->GSSetShader(gs, NULL, 0); + ctx->PSSetShader(ps, NULL, 0); + + ctx->OMSetRenderTargets(1, &bbRTV.GetInterfacePtr(), NULL); + + RSSetViewport({screenWidth / 4.0f, 0.0f, (float)screenWidth / 4.0f, + (float)screenHeight / 4.0f, 0.0f, 1.0f}); + + ctx->IASetVertexBuffers(0, 2, bufs, &strides[0], offs); + ctx->IASetInputLayout(streamoutLayout); + ctx->DrawAuto(); + Present(); } diff --git a/util/test/demos/demos.vcxproj b/util/test/demos/demos.vcxproj index 0d927c0cd..0b489f948 100644 --- a/util/test/demos/demos.vcxproj +++ b/util/test/demos/demos.vcxproj @@ -145,7 +145,7 @@ - + diff --git a/util/test/demos/demos.vcxproj.filters b/util/test/demos/demos.vcxproj.filters index 506bd0e35..8acd6803b 100644 --- a/util/test/demos/demos.vcxproj.filters +++ b/util/test/demos/demos.vcxproj.filters @@ -70,9 +70,6 @@ OpenGL\demos - - D3D11\demos - D3D11\demos @@ -309,6 +306,9 @@ Vulkan\demos + + D3D11\demos + diff --git a/util/test/tests/D3D11/D3D11_Stream_Out.py b/util/test/tests/D3D11/D3D11_Stream_Out.py new file mode 100644 index 000000000..f67c60f9c --- /dev/null +++ b/util/test/tests/D3D11/D3D11_Stream_Out.py @@ -0,0 +1,58 @@ +import rdtest +import struct +import renderdoc as rd + + +class D3D11_Stream_Out(rdtest.TestCase): + demos_test_name = 'D3D11_Stream_Out' + + def check_capture(self): + draw = self.find_draw("Draw") + + self.check(draw is not None) + + self.controller.SetFrameEvent(draw.eventId, False) + + pipe: rd.PipeState = self.controller.GetPipelineState() + + # Get the input data as our reference + + # First draw should have data at offset 0. First buffer has positions, second has colors (with doubled stride) + + vsin = self.get_vsin(draw) + + pos = [(*v['POSITION'], 1.0) for v in vsin] + col = [v['COLOR'] for v in vsin] + + d3d11pipe: rd.D3D11State = self.controller.GetD3D11PipelineState() + + so: rd.D3D11StreamOut = d3d11pipe.streamOut + so_bytes = self.controller.GetBufferData(so.outputs[0].resourceId, so.outputs[0].byteOffset, 0) + + for i,p in enumerate(pos): + so_p = struct.unpack_from("4f", so_bytes, 0 + 4*4*i) + if not rdtest.value_compare(p, so_p): + raise rdtest.TestFailureException("Streamed-out position {} doesn't match expected {}".format(so_p, p)) + + so_bytes = self.controller.GetBufferData(so.outputs[1].resourceId, so.outputs[1].byteOffset, 0) + + for i,c in enumerate(col): + so_c = struct.unpack_from("4f", so_bytes, 0 + 8*4*i) + if not rdtest.value_compare(c, so_c): + raise rdtest.TestFailureException("Streamed-out color {} doesn't match expected {}".format(so_c, c)) + + draw_auto = self.find_draw("DrawAuto", draw.eventId) + + # First draw should be 3 vertices + if not rdtest.value_compare(draw_auto.numIndices, 3): + raise rdtest.TestFailureException("First DrawAuto() draws {} vertices".format(draw_auto.numIndices)) + + draw_auto = self.find_draw("DrawAuto", draw_auto.eventId+1) + + # Second draw should be 6 vertices (3 vertices, instanced twice + if not rdtest.value_compare(draw_auto.numIndices, 6): + raise rdtest.TestFailureException("Second DrawAuto() draws {} vertices".format(draw_auto.numIndices)) + if not rdtest.value_compare(draw_auto.numInstances, 1): + raise rdtest.TestFailureException("Second DrawAuto() draws {} instances".format(draw_auto.numInstances)) + + rdtest.log.success("First draw stream-out data is correct")