Esempio n. 1
0
    def check_modifs_consistent(self, modifs):
        # postmod of each should match premod of the next
        for i in range(len(modifs) - 1):
            a = value_selector(modifs[i].postMod.col)
            b = value_selector(modifs[i + 1].preMod.col)

            if self.is_depth:
                a = (modifs[i].postMod.depth, modifs[i].postMod.stencil)
                b = (modifs[i + 1].preMod.depth, modifs[i + 1].preMod.stencil)

            if a != b:
                raise rdtest.TestFailureException(
                    "postmod at {} primitive {}: {} doesn't match premod at {} primitive {}: {}"
                    .format(modifs[i].eventId, modifs[i].primitiveID, a,
                            modifs[i + 1].eventId, modifs[i + 1].primitiveID,
                            b))

        # Check that if the test failed, its postmod is the same as premod
        for i in range(len(modifs)):
            if not modifs[i].Passed():
                a = value_selector(modifs[i].preMod.col)
                b = value_selector(modifs[i].postMod.col)

                if self.is_depth:
                    a = (modifs[i].preMod.depth, modifs[i].preMod.stencil)
                    b = (modifs[i].postMod.depth, modifs[i].postMod.stencil)

                if not rdtest.value_compare(a, b):
                    raise rdtest.TestFailureException(
                        "postmod at {} primitive {}: {} doesn't match premod: {}"
                        .format(modifs[i].eventId, modifs[i].primitiveID, b,
                                a))
Esempio n. 2
0
    def check_debug(self, vtx, idx, inst, postvs):
        trace: rd.ShaderDebugTrace = self.controller.DebugVertex(vtx, inst, idx, 0)

        if trace.debugger is None:
            self.controller.FreeTrace(trace)

            raise rdtest.TestFailureException("Couldn't debug vertex {} in instance {}".format(vtx, inst))

        cycles, variables = self.process_trace(trace)

        for var in trace.sourceVars:
            var: rd.SourceVariableMapping
            if var.variables[0].type == rd.DebugVariableType.Variable and var.signatureIndex >= 0:
                name = var.name

                if name not in postvs[vtx].keys():
                    raise rdtest.TestFailureException("Don't have expected output for {}".format(name))

                expect = postvs[vtx][name]
                value = self.evaluate_source_var(var, variables)

                if len(expect) != value.columns:
                    raise rdtest.TestFailureException(
                        "Output {} at vert {} (idx {}) instance {} has different size ({} values) to expectation ({} values)"
                            .format(name, vtx, idx, inst, value.columns, len(expect)))

                debugged = value.value.f32v[0:value.columns]

                if not rdtest.value_compare(expect, debugged):
                    raise rdtest.TestFailureException(
                        "Debugged value {} at vert {} (idx {}) instance {}: {} doesn't exactly match postvs output {}".format(
                            name, vtx, idx, inst, debugged, expect))
        rdtest.log.success('Successfully debugged vertex {} in instance {}'
                           .format(vtx, inst))
Esempio n. 3
0
    def check_compute(self, eventId):
        action = self.find_action("Dispatch", eventId)
        self.check(action is not None)
        self.controller.SetFrameEvent(action.eventId, False)

        pipe = self.controller.GetD3D12PipelineState()

        if len(pipe.rootElements) != 2:
            raise rdtest.TestFailureException(
                "Wrong number of root elements is bound: {}, not 2".format(
                    len(pipe.rootElements)))

        root = pipe.rootElements[0]
        # second root element is the cbuffer const, we don't care

        if root.dynamicallyUsedCount != 1:
            raise rdtest.TestFailureException(
                "Compute root range 0 has {} dynamically used, not 1".format(
                    root.dynamicallyUsedCount))

        if not root.views[15].dynamicallyUsed:
            raise rdtest.TestFailureException(
                "Compute root range 0[15] isn't dynamically used")

        for i in range(len(root.views)):
            if i == 15:
                continue

            if root.views[i].dynamicallyUsed:
                raise rdtest.TestFailureException(
                    "Compute root range 0[{}] i dynamically used".format(i))
Esempio n. 4
0
    def check_capture(self):
        self.check_final_backbuffer()

        # Open the capture and grab the thumbnail, check that it is all green too (dirty way of verifying we didn't
        # break in-app updates but somehow end up with the right data)
        cap = rd.OpenCaptureFile()

        # Open a particular file
        status = cap.OpenFile(self.capture_filename, '', None)

        # Make sure the file opened successfully
        if status != rd.ReplayStatus.Succeeded:
            cap.Shutdown()
            raise rdtest.TestFailureException("Couldn't open '{}': {}".format(
                self.capture_filename, str(status)))

        thumb: rd.Thumbnail = cap.GetThumbnail(rd.FileType.PNG, 0)

        tmp_path = rdtest.get_tmp_path('thumbnail.png')

        with open(tmp_path, 'wb') as f:
            f.write(thumb.data)

        # The original thumbnail should also be identical, since we have the uncompressed extended thumbnail.
        ref_path = self.get_ref_path('backbuffer.png')

        if not rdtest.png_compare(tmp_path, ref_path):
            raise rdtest.TestFailureException(
                "Reference backbuffer and thumbnail image differ", tmp_path,
                ref_path)

        rdtest.log.success("Thumbnail is identical to reference")
Esempio n. 5
0
    def check_capture(self):
        sdf = self.controller.GetStructuredFile()

        # The marker name, and the calls that we expect to follow it
        expected = {
            'First Test': ['glUniform1ui'],
            'Second Test': ['glVertexAttribBinding', 'glProgramUniform4f'],
            'Third Test': ['glVertexArrayAttribBinding', 'glUniform4f'],
        }

        for test in expected.keys():
            marker: rd.DrawcallDescription = self.find_draw(test)
            if marker is None:
                raise rdtest.TestFailureException(
                    'Failed to find draw {}'.format(test))
            draw: rd.DrawcallDescription = marker.next

            calls = []

            ev: rd.APIEvent
            for ev in draw.events:
                # skip any events up to and including the marker itself
                if ev.eventId <= marker.eventId:
                    continue

                calls.append(sdf.chunks[ev.chunkIndex].name)

            for i in range(len(expected[test])):
                if expected[test][i] != calls[i]:
                    raise rdtest.TestFailureException(
                        'After marker {} got call {} but expected {}'.format(
                            test, calls[i], expected[test][i]))

        rdtest.log.success("API calls are as expected")
    def run(self):
        self.capture_filename = self.get_capture()

        self.check(os.path.exists(self.capture_filename), "Didn't generate capture in make_capture")

        rdtest.log.print("Loading capture")

        memory_before: int = rd.GetCurrentProcessMemoryUsage()
        start_time = time.time()

        self.controller = rdtest.open_capture(self.capture_filename, opts=self.get_replay_options())

        duration = time.time() - start_time
        memory_after: int = rd.GetCurrentProcessMemoryUsage()

        memory_increase = memory_after - memory_before

        rdtest.log.print("Loaded capture in {:02} seconds, consuming {} bytes of memory".format(duration, memory_increase))

        if memory_increase > 1200*1000*1000:
            raise rdtest.TestFailureException("Memory usage is too high".format(duration))
        else:
            rdtest.log.success("Memory usage is OK")

        if rd.IsReleaseBuild():
            if duration >= 2.5:
                raise rdtest.TestFailureException("Time to load is too high")
            rdtest.log.success("Time to load is OK")
        else:
            rdtest.log.print("Not checking time to load in non-release build")

        if self.controller is not None:
            self.controller.Shutdown()
Esempio n. 7
0
    def check_capture(self):
        self.check_final_backbuffer()

        draw = self.find_draw("Primary")

        resources = self.controller.GetResources()

        self.check(draw is not None and draw.next is not None)

        self.controller.SetFrameEvent(draw.next.eventId, False)

        pipe: rd.PipeState = self.controller.GetPipelineState()

        self.check(pipe.GetVBuffers()[0].byteOffset == 0)
        rdtest.log.success("Primary draw has correct byte offset")

        pipeline: rd.ResourceId = self.controller.GetVulkanPipelineState(
        ).graphics.pipelineResourceId

        checked = False
        res: rd.ResourceDescription
        for res in resources:
            if res.resourceId == pipeline:
                self.check(res.name == "Pipeline 0")
                checked = True

        if not checked:
            raise rdtest.TestFailureException(
                "Couldn't find resource description for pipeline {}".format(
                    pipeline))

        rdtest.log.success("Primary draw has correct pipeline bound")

        draw = self.find_draw("Secondary")

        self.check(draw is not None and draw.next is not None)

        self.controller.SetFrameEvent(draw.next.eventId, False)

        pipe: rd.PipeState = self.controller.GetPipelineState()

        self.check(pipe.GetVBuffers()[0].byteOffset == 108)
        rdtest.log.success("Secondary draw has correct byte offset")

        pipeline: rd.ResourceId = self.controller.GetVulkanPipelineState(
        ).graphics.pipelineResourceId

        checked = False
        res: rd.ResourceDescription
        for res in resources:
            if res.resourceId == pipeline:
                self.check(res.name == "Pipeline 1")
                checked = True

        if not checked:
            raise rdtest.TestFailureException(
                "Couldn't find resource description for pipeline {}".format(
                    pipeline))

        rdtest.log.success("Secondary draw has correct pipeline bound")
Esempio n. 8
0
    def check_capture(self):
        tex = rd.TextureDisplay()

        # At each action, the centre pixel of the viewport should be green
        action = self.get_first_action()
        while action is not None:
            self.controller.SetFrameEvent(action.eventId, False)

            if action.flags & rd.ActionFlags.Drawcall:
                pipe = self.controller.GetPipelineState()
                tex = self.controller.GetPipelineState().GetOutputTargets()[0].resourceId

                view: rd.Viewport = self.controller.GetPipelineState().GetViewport(0)

                x,y = int(view.x + view.width / 2), int(view.y + view.height / 2)

                # convert to top-left co-ordinates for use with PickPixel
                y = self.get_texture(tex).height - y

                self.check_pixel_value(tex, x, y, [0.0, 1.0, 0.0, 1.0])

            action = action.next

        rdtest.log.success("Draws are all green")

        # Now save the backbuffer to disk
        ref_path = rdtest.get_tmp_path('backbuffer.png')

        save_data = rd.TextureSave()
        save_data.resourceId = tex
        save_data.destType = rd.FileType.PNG

        self.controller.SaveTexture(save_data, ref_path)

        # Open the capture and grab the thumbnail, check that it is all green too (dirty way of verifying we didn't
        # break in-app updates but somehow end up with the right data)
        cap = rd.OpenCaptureFile()

        # Open a particular file
        status = cap.OpenFile(self.capture_filename, '', None)

        # Make sure the file opened successfully
        if status != rd.ReplayStatus.Succeeded:
            cap.Shutdown()
            raise rdtest.TestFailureException("Couldn't open '{}': {}".format(self.capture_filename, str(status)))

        thumb: rd.Thumbnail = cap.GetThumbnail(rd.FileType.PNG, 0)

        tmp_path = rdtest.get_tmp_path('thumbnail.png')

        with open(tmp_path, 'wb') as f:
            f.write(thumb.data)

        # The original thumbnail should also be identical, since we have the uncompressed extended thumbnail.

        if not rdtest.png_compare(tmp_path, ref_path):
            raise rdtest.TestFailureException("Reference backbuffer and thumbnail image differ", tmp_path, ref_path)

        rdtest.log.success("Thumbnail is identical to reference")
Esempio n. 9
0
    def check_capture(self):
        last_action: rd.ActionDescription = self.get_last_action()

        self.controller.SetFrameEvent(last_action.eventId, True)

        action: rd.ActionDescription = self.find_action('Duration')

        min_duration = float(action.customName.split(' = ')[1])

        if rd.IsReleaseBuild():
            if min_duration >= 15.0:
                raise rdtest.TestFailureException(
                    "Minimum duration noted {} ms is too high".format(
                        min_duration))
            rdtest.log.success(
                "Minimum duration ({}) is OK".format(min_duration))
        else:
            rdtest.log.print(
                "Not checking duration ({}) in non-release build".format(
                    min_duration))

        resources = self.controller.GetResources()
        for i in range(8):
            res: rd.ResourceDescription = [
                r for r in resources if r.name == 'Offscreen{}'.format(i)
            ][0]
            tex: rd.TextureDescription = self.get_texture(res.resourceId)

            data = self.controller.GetTextureData(res.resourceId,
                                                  rd.Subresource(0, 0, 0))

            pixels = [
                struct.unpack_from("4f", data, 16 * p)
                for p in range(tex.width * tex.height)
            ]

            unique_pixels = list(set(pixels))

            if len(unique_pixels) > 2:
                raise rdtest.TestFailureException(
                    "Too many pixel values found ({})".format(
                        len(unique_pixels)))

            if (0.0, 0.0, 0.0, 1.0) not in unique_pixels:
                raise rdtest.TestFailureException(
                    "Didn't find background colour in unique pixels list")

            unique_pixels.remove((0.0, 0.0, 0.0, 1.0))

            if not rdtest.value_compare(
                (0.8, 0.8, 0.8, 0.4), unique_pixels[0]):
                raise rdtest.TestFailureException(
                    "Didn't find foreground colour in unique pixels list")

            rdtest.log.success("{} has correct contents".format(res.name))
Esempio n. 10
0
    def check_capture(self):
        # Make an output so we can pick pixels
        out: rd.ReplayOutput = self.controller.CreateOutput(
            rd.CreateHeadlessWindowingData(100, 100),
            rd.ReplayOutputType.Texture)

        self.check(out is not None)

        # find the first draw
        draw = self.find_draw("Draw")

        # check the centre pixel of the viewport is white
        self.controller.SetFrameEvent(draw.eventId, False)

        pipe: rd.PipeState = self.controller.GetPipelineState()

        tex = rd.TextureDisplay()
        tex.resourceId = pipe.GetOutputTargets()[0].resourceId
        out.SetTextureDisplay(tex)

        view: rd.Viewport = pipe.GetViewport(0)

        picked: rd.PixelValue = out.PickPixel(tex.resourceId, False,
                                              int(view.width / 2),
                                              int(view.height / 2), 0, 0, 0)

        if not rdtest.value_compare(picked.floatValue, [1.0, 1.0, 1.0, 1.0]):
            raise rdtest.TestFailureException(
                "Picked value {} doesn't match expectation".format(
                    picked.floatValue))

        rdtest.log.success("Picked value for first draw is as expected")

        # find the second draw
        draw = self.find_draw("Draw", draw.eventId + 1)

        pipe: rd.PipeState = self.controller.GetPipelineState()

        tex.resourceId = pipe.GetOutputTargets()[0].resourceId
        out.SetTextureDisplay(tex)

        view: rd.Viewport = pipe.GetViewport(0)

        picked: rd.PixelValue = out.PickPixel(tex.resourceId, False,
                                              int(view.width / 2),
                                              int(view.height / 2), 0, 0, 0)

        if not rdtest.value_compare(picked.floatValue, [1.0, 1.0, 1.0, 1.0]):
            raise rdtest.TestFailureException(
                "Picked value {} doesn't match expectation".format(
                    picked.floatValue))

        rdtest.log.success("Picked value for second draw is as expected")
Esempio n. 11
0
    def check_capture(self):
        if not self.controller.GetAPIProperties().shaderDebugging:
            rdtest.log.success("Shader debugging not enabled, skipping test")
            return

        failed = False

        test_marker: rd.ActionDescription = self.find_action("action")
        while test_marker is not None:
            action = test_marker.next
            event_name = test_marker.customName
            test_marker: rd.ActionDescription = self.find_action(
                "action", action.eventId)

            self.controller.SetFrameEvent(action.eventId, False)
            pipe: rd.PipeState = self.controller.GetPipelineState()

            if not pipe.GetShaderReflection(
                    rd.ShaderStage.Pixel).debugInfo.debuggable:
                rdtest.log.print(
                    "Skipping undebuggable shader at {}.".format(event_name))
                continue

            # Debug the shader
            trace: rd.ShaderDebugTrace = self.controller.DebugPixel(
                200, 150, rd.ReplayController.NoPreference,
                rd.ReplayController.NoPreference)
            if trace.debugger is None:
                failed = True
                rdtest.log.error(
                    "Test {} could not be debugged.".format(event_name))
                continue

            cycles, variables = self.process_trace(trace)

            output = self.find_output_source_var(trace,
                                                 rd.ShaderBuiltin.ColorOutput,
                                                 0)

            debugged = self.evaluate_source_var(output, variables)

            try:
                self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId,
                                       200, 150, debugged.value.f32v[0:4])
            except rdtest.TestFailureException as ex:
                failed = True
                rdtest.log.error("Test {} did not match. {}".format(
                    event_name, str(ex)))
                continue
            finally:
                self.controller.FreeTrace(trace)

            rdtest.log.success(
                "Test {} matched as expected".format(event_name))

        if failed:
            raise rdtest.TestFailureException(
                "Some tests were not as expected")

        rdtest.log.success("All tests matched")
Esempio n. 12
0
    def check_clearbeforedraw_depth(self, out, depthId):
        # Test ClearBeforeDraw with a depth target
        tex = rd.TextureDisplay()
        tex.overlay = rd.DebugOverlay.ClearBeforeDraw
        tex.resourceId = depthId

        out.SetTextureDisplay(tex)
        out.GetDebugOverlayTexID() # Called to refresh the overlay
        
        overlay = rd.DebugOverlay.ClearBeforeDraw
        test_name = str(overlay) + '.Depth'

        overlay_path = rdtest.get_tmp_path(test_name + '.png')
        ref_path = self.get_ref_path(test_name + '.png')

        save_data = rd.TextureSave()
        save_data.resourceId = depthId
        save_data.destType = rd.FileType.PNG
        save_data.channelExtract = 0

        tolerance = 2

        self.controller.SaveTexture(save_data, overlay_path)

        if not rdtest.png_compare(overlay_path, ref_path, tolerance):
            raise rdtest.TestFailureException("Reference and output image differ for overlay {}".format(test_name), overlay_path, ref_path)

        rdtest.log.success("Reference and output image are identical for {}".format(test_name))
Esempio n. 13
0
    def check_capture(self):
        if not self.controller.GetAPIProperties().shaderDebugging:
            rdtest.log.success("Shader debugging not enabled, skipping test")
            return

        success = True

        # Jump to the draw
        test_marker: rd.DrawcallDescription = self.find_draw("Test")

        # Draw 1: No GS, PS without prim
        draw = test_marker.next
        success &= self.test_draw(draw, 100, 80, rd.ReplayController.NoPreference, [0], [0, 1, 0, 1])

        # Draw 2: No GS, PS with prim
        draw = draw.next
        success &= self.test_draw(draw, 300, 80, rd.ReplayController.NoPreference, [0], [0, 1, 0, 1])

        # Draw 3: GS, PS without prim
        draw = draw.next
        success &= self.test_draw(draw, 125, 250, rd.ReplayController.NoPreference, [0], [0, 1, 0, 1])

        # Draw 4: GS, PS with prim
        draw = draw.next
        success &= self.test_draw(draw, 325, 250, 2, [2], [0.5, 1, 0, 1])
        success &= self.test_draw(draw, 325, 250, 3, [3], [0.75, 1, 0, 1])
        # No expected output here, since it's nondeterministic which primitive gets selected
        success &= self.test_draw(draw, 325, 250, rd.ReplayController.NoPreference, [2, 3], None)

        if not success:
            raise rdtest.TestFailureException("Some tests were not as expected")

        rdtest.log.success("All tests matched")
    def check_capture(self):
        draw = self.find_draw("Draw")

        self.check(draw is not None)

        self.controller.SetFrameEvent(draw.eventId, False)

        # Make an output so we can pick pixels
        out: rd.ReplayOutput = self.controller.CreateOutput(rd.CreateHeadlessWindowingData(100, 100), rd.ReplayOutputType.Texture)

        pipe: rd.PipeState = self.controller.GetPipelineState()

        tex = rd.TextureDisplay()
        tex.resourceId = pipe.GetOutputTargets()[0].resourceId
        out.SetTextureDisplay(tex)

        texdetails = self.get_texture(tex.resourceId)

        picked: rd.PixelValue = out.PickPixel(tex.resourceId, False,
                                              int(texdetails.width / 2), int(texdetails.height / 2), 0, 0, 0)

        if not rdtest.value_compare(picked.floatValue, [1.0, 0.0, 0.0, 1.0]):
            raise rdtest.TestFailureException("Picked value {} doesn't match expectation".format(picked.floatValue))

        rdtest.log.success("picked value is as expected")

        out.Shutdown()
Esempio n. 15
0
    def check_region(self, region, test):
        colors = self.get_region_cols(region)

        if not test(colors):
            tmp_path = rdtest.get_tmp_path('output.png')
            rdtest.png_save(tmp_path, self.rows, self.out.GetDimensions(), False)
            raise rdtest.TestFailureException("Expected line segment wrong, colors: {}".format(colors), tmp_path)
    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()

        stage = rd.ShaderStage.Pixel

        cbuf: rd.BoundCBuffer = pipe.GetConstantBuffer(stage, 0, 0)

        variables = self.controller.GetCBufferVariableContents(
            pipe.GetGraphicsPipelineObject(), pipe.GetShader(stage),
            pipe.GetShaderEntryPoint(stage), 0, cbuf.resourceId,
            cbuf.byteOffset, cbuf.byteSize)

        outcol: rd.ShaderVariable = variables[1]

        self.check(outcol.name == "outcol")
        if not rdtest.value_compare(outcol.value.fv[0:4],
                                    [0.0, 0.0, 0.0, 0.0]):
            raise rdtest.TestFailureException(
                "expected outcol to be 0s, but got {}".format(
                    outcol.value.fv[0:4]))

        rdtest.log.success("CBuffer value was truncated as expected")
Esempio n. 17
0
    def check_vertex(self, x, y, result):
        pick = self.out.PickVertex(x, y)

        if not rdtest.value_compare(result, pick):
            raise rdtest.TestFailureException("When picking ({},{}) expected vertex {} in instance {}, but found {} in {}".format(x, y, result[0], result[1], pick[0], pick[1]))

        rdtest.log.success("Picking {},{} returns vertex {} in instance {} as expected".format(x, y, result[0], result[1]))
Esempio n. 18
0
    def check_capture_with_controller(self, proxy_api: str):
        any_failed = False

        if proxy_api != '':
            rdtest.log.print('Running with {} local proxy'.format(proxy_api))
            self.proxied = True
        else:
            rdtest.log.print('Running on direct replay')
            self.proxied = False

        for d in self.controller.GetDrawcalls():

            # Check each region for the tests within
            if d.flags & rd.DrawFlags.PushMarker:
                name = ''
                tests_run = 0

                failed = False

                # Iterate over drawcalls in this region
                for sub in d.children:
                    sub: rd.DrawcallDescription

                    if sub.flags & rd.DrawFlags.SetMarker:
                        name = sub.name

                    # Check this draw
                    if sub.flags & rd.DrawFlags.Drawcall:
                        tests_run = tests_run + 1
                        try:
                            # Set this event as current
                            self.controller.SetFrameEvent(sub.eventId, True)

                            self.filename = (d.name + '@' + name).replace(
                                '->', '_')

                            self.check_test(d.name, name,
                                            Texture_Zoo.TEST_CAPTURE)
                        except rdtest.TestFailureException as ex:
                            failed = any_failed = True
                            rdtest.log.error(str(ex))

                if not failed:
                    rdtest.log.success(
                        "All {} texture tests for {} are OK".format(
                            tests_run, d.name))

        if not any_failed:
            if proxy_api != '':
                rdtest.log.success(
                    'All textures are OK with {} as local proxy'.format(
                        proxy_api))
            else:
                rdtest.log.success("All textures are OK on direct replay")
        else:
            raise rdtest.TestFailureException(
                "Some tests were not as expected")
Esempio n. 19
0
    def check_capture(self):

        draw = self.find_draw("Draw")

        self.check(draw is not None)

        self.controller.SetFrameEvent(draw.eventId, False)

        pipe: rd.VKState = self.controller.GetVulkanPipelineState()

        # Check bindings:
        #   - buffer 15 in bind 0 should be used
        #   - images 19, 20, 21 in bind 1 should be used for the non-uniform index
        #     images 49 & 59 in bind 1 should be used for the first fixed index
        #   - images 381 & 386 in bind 2 should be used for the second fixed index
        bind_info = {
            0: { 'dynamicallyUsedCount': 1, 'used': [15] },
            1: { 'dynamicallyUsedCount': 5, 'used': [19, 20, 21, 49, 59] },
            2: { 'dynamicallyUsedCount': 2, 'used': [381, 386] },
        }

        if len(pipe.graphics.descriptorSets) != 1:
            raise rdtest.TestFailureException("Wrong number of sets is bound: {}, not 1".format(len(pipe.graphics.descriptorSets)))

        desc_set: rd.VKDescriptorSet = pipe.graphics.descriptorSets[0]

        binding: rd.VKDescriptorBinding
        for bind, binding in enumerate(desc_set.bindings):
            if binding.dynamicallyUsedCount != bind_info[bind]['dynamicallyUsedCount']:
                raise rdtest.TestFailureException("Bind {} doesn't have the right used count. {} is not the expected count of {}"
                                                  .format(bind, binding.dynamicallyUsedCount, bind_info[bind]['dynamicallyUsedCount']))

            el: rd.VKBindingElement
            for idx, el in enumerate(binding.binds):
                expected_used = idx in bind_info[bind]['used']
                actually_used = el.dynamicallyUsed

                if expected_used and not actually_used:
                    raise rdtest.TestFailureException("Bind {} element {} expected to be used, but isn't.".format(bind, idx))

                if not expected_used and actually_used:
                    raise rdtest.TestFailureException("Bind {} element {} expected to be unused, but is.".format(bind, idx))

        rdtest.log.success("Dynamic usage is as expected")
Esempio n. 20
0
    def check_capture(self):
        memory: int = rd.GetCurrentProcessMemoryUsage()

        if memory > 500 * 1000 * 1000:
            raise rdtest.TestFailureException(
                "Memory usage of {} is too high".format(memory))

        rdtest.log.success(
            "Capture {} opened with reasonable memory ({})".format(
                self.demos_frame_cap, memory))
Esempio n. 21
0
    def check_capture(self):
        if not self.controller.GetAPIProperties().shaderDebugging:
            rdtest.log.success("Shader debugging not enabled, skipping test")
            return

        failed = False

        for test_name in ["GLSL1 tests", "GLSL2 tests", "ASM tests"]:
            rdtest.log.begin_section(test_name)
            action = self.find_action(test_name)
            for child in range(len(action.children)):
                section = action.children[child]
                self.controller.SetFrameEvent(section.eventId, False)
                pipe: rd.PipeState = self.controller.GetPipelineState()

                if not pipe.GetShaderReflection(rd.ShaderStage.Pixel).debugInfo.debuggable:
                    rdtest.log.print("Skipping undebuggable shader at {} in {}.".format(child, test_name))
                    return

                for test in range(section.numInstances):
                    x = 4 * test + 1
                    y = 4 * child + 1

                    # Debug the shader
                    trace: rd.ShaderDebugTrace = self.controller.DebugPixel(x, y, rd.ReplayController.NoPreference,
                                                                            rd.ReplayController.NoPreference)

                    if trace.debugger is None:
                        failed = True
                        rdtest.log.error("Test {} in sub-section {} did not debug at all".format(test, child))
                        self.controller.FreeTrace(trace)
                        continue

                    cycles, variables = self.process_trace(trace)

                    output: rd.SourceVariableMapping = self.find_output_source_var(trace, rd.ShaderBuiltin.ColorOutput, 0)

                    debugged = self.evaluate_source_var(output, variables)

                    try:
                        self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId, x, y, debugged.value.f32v[0:4])
                    except rdtest.TestFailureException as ex:
                        failed = True
                        rdtest.log.error("Test {} in sub-section {} did not match. {}".format(test, child, str(ex)))
                        continue
                    finally:
                        self.controller.FreeTrace(trace)

                    rdtest.log.success("Test {} in sub-section {} matched as expected".format(test, child))
            rdtest.log.end_section(test_name)

        if failed:
            raise rdtest.TestFailureException("Some tests were not as expected")

        rdtest.log.success("All tests matched")
Esempio n. 22
0
    def check_capture(self):
        # Need capture access. Rather than trying to keep the original around, we just open a new one
        cap = rd.OpenCaptureFile()

        # Open a particular file
        status = cap.OpenFile(self.capture_filename, '', None)

        # Make sure the file opened successfully
        if status != rd.ReplayStatus.Succeeded:
            cap.Shutdown()
            raise rdtest.TestFailureException(
                "Couldn't open capture for access: {}".format(
                    self.capture_filename, str(status)))

        if not cap.HasCallstacks():
            raise rdtest.TestFailureException(
                "Capture does not report having callstacks")

        if not cap.InitResolver(False, None):
            raise rdtest.TestFailureException(
                "Failed to initialise callstack resolver")

        draw = self.find_draw("Draw")

        event: rd.APIEvent = draw.events[-1]

        expected_funcs = [
            "GL_Callstacks::testFunction",
            "GL_Callstacks::main",
        ]

        expected_lines = [7001, 8002]

        callstack = cap.GetResolve(list(event.callstack))

        if len(callstack) < len(expected_funcs):
            raise rdtest.TestFailureException(
                "Resolved callstack isn't long enough ({} stack frames), expected at least {}"
                .format(len(event.callstack), len(expected_funcs)))

        for i in range(len(expected_funcs)):
            stack: str = callstack[i]
            if expected_funcs[i] not in stack:
                raise rdtest.TestFailureException(
                    "Expected '{}' in '{}'".format(expected_funcs[i], stack))
            idx = callstack[i].find("line")
            if idx < 0:
                raise rdtest.TestFailureException(
                    "Expected a line number in '{}'".format(stack))

            if int(stack[idx + 5:]) != expected_lines[i]:
                raise rdtest.TestFailureException(
                    "Expected line number {} in '{}'".format(
                        expected_lines[i], stack))

        rdtest.log.success("Callstacks are as expected")
Esempio n. 23
0
    def find_draw(self, name):
        draw = None

        for d in self.controller.GetDrawcalls():
            if name in d.name:
                draw = d
                break

        if draw is None:
            raise rdtest.TestFailureException("Couldn't find '{}' draw".format(name))

        return draw
Esempio n. 24
0
    def check_capture(self):
        last_draw: rd.DrawcallDescription = self.get_last_draw()

        self.controller.SetFrameEvent(last_draw.eventId, True)

        tex = last_draw.copyDestination

        # green background around first triangle, blue around second
        self.check_pixel_value(tex, 10, 10, [0.0, 1.0, 0.0, 1.0])
        self.check_pixel_value(tex, 118, 10, [0.0, 1.0, 0.0, 1.0])
        self.check_pixel_value(tex, 118, 118, [0.0, 1.0, 0.0, 1.0])
        self.check_pixel_value(tex, 10, 118, [0.0, 1.0, 0.0, 1.0])

        self.check_pixel_value(tex, 138, 10, [0.0, 0.0, 1.0, 1.0])
        self.check_pixel_value(tex, 246, 10, [0.0, 0.0, 1.0, 1.0])
        self.check_pixel_value(tex, 246, 118, [0.0, 0.0, 1.0, 1.0])
        self.check_pixel_value(tex, 138, 118, [0.0, 0.0, 1.0, 1.0])

        # Sample across each triangle, we expect things to be identical
        for xoffs in [0, 128]:
            # Check black checkerboard squares
            self.check_pixel_value(tex, xoffs + 42, 92, [0.0, 0.0, 0.0, 1.0])
            self.check_pixel_value(tex, xoffs + 40, 85, [0.0, 0.0, 0.0, 1.0])
            self.check_pixel_value(tex, xoffs + 68, 66, [0.0, 0.0, 0.0, 1.0])
            self.check_pixel_value(tex, xoffs + 59, 47, [0.0, 0.0, 0.0, 1.0])
            self.check_pixel_value(tex, xoffs + 81, 92, [0.0, 0.0, 0.0, 1.0])

            # Check the red and green eyes of the smiley
            self.check_pixel_value(tex, xoffs + 49, 83, [1.0, 0.0, 0.09, 1.0])
            self.check_pixel_value(tex, xoffs + 60, 83, [0.0, 1.0, 0.09, 1.0])

            # Check the blue smile
            self.check_pixel_value(tex, xoffs + 64, 72, [0.09, 0.0, 1.0, 1.0])

            # Check the orange face
            self.check_pixel_value(tex, xoffs + 46, 86,
                                   [1.0, 0.545, 0.36, 1.0])

            # Check the empty space where we clamped and didn't repeat
            self.check_pixel_value(tex, xoffs + 82, 79, [0.72, 1.0, 1.0, 1.0])
            self.check_pixel_value(tex, xoffs + 84, 86, [0.72, 1.0, 1.0, 1.0])
            self.check_pixel_value(tex, xoffs + 88, 92, [0.72, 1.0, 1.0, 1.0])

            # Check that the repeated smiley above is there
            self.check_pixel_value(tex, xoffs + 67, 53,
                                   [0.905, 0.635, 0.36, 1.0])
            self.check_pixel_value(tex, xoffs + 65, 50, [1.0, 0.0, 0.09, 1.0])

        # Check for resource leaks
        if len(self.controller.GetResources()) > 75:
            raise rdtest.TestFailureException(
                "Too many resources found: {}".format(
                    len(self.controller.GetResources())))
Esempio n. 25
0
    def check_capture(self):
        apiprops: rd.APIProperties = self.controller.GetAPIProperties()

        if not apiprops.rgpCapture:
            rdtest.log.print("RGP capture not tested")
            return

        path = self.controller.CreateRGPProfile(rd.CreateHeadlessWindowingData(100, 100))

        if os.path.exists(path) and os.path.getsize(path) > 100:
            rdtest.log.success("RGP capture created successfully")
        else:
            raise rdtest.TestFailureException("RGP capture failed")
Esempio n. 26
0
 def check_events(self, events, modifs):
     self.check(len(modifs) == len(events))
     # Check for consistency first
     self.check_modifs_consistent(modifs)
     for i in range(len(modifs)):
         for c in range(len(events[i])):
             expected = events[i][c][1]
             actual = events[i][c][0](modifs[i])
             if not rdtest.value_compare(actual, expected):
                 raise rdtest.TestFailureException(
                     "eventId {}, testing {} expected {}, got {}".format(
                         modifs[i].eventId, events[i][c][0].__name__,
                         expected, actual))
Esempio n. 27
0
    def find_action(self, name):
        action = None

        for d in self.controller.GetRootActions():
            if name in d.customName:
                action = d
                break

        if action is None:
            raise rdtest.TestFailureException(
                "Couldn't find '{}' action".format(name))

        return action
Esempio n. 28
0
    def check_modifs_consistent(self, modifs):
        # postmod of each should match premod of the next
        for i in range(len(modifs) - 1):
            if value_selector(modifs[i].postMod.col) != value_selector(
                    modifs[i + 1].preMod.col):
                raise rdtest.TestFailureException(
                    "postmod at {}: {} doesn't match premod at {}: {}".format(
                        modifs[i].eventId,
                        value_selector(modifs[i].postMod.col),
                        modifs[i + 1].eventId,
                        value_selector(modifs[i].preMod.col)))

        # Check that if the test failed, its postmod is the same as premod
        for i in range(len(modifs)):
            if not modifs[i].Passed():
                if not rdtest.value_compare(
                        value_selector(modifs[i].preMod.col),
                        value_selector(modifs[i].postMod.col)):
                    raise rdtest.TestFailureException(
                        "postmod at {}: {} doesn't match premod: {}".format(
                            modifs[i].eventId,
                            value_selector(modifs[i].postMod.col),
                            value_selector(modifs[i].preMod.col)))
Esempio n. 29
0
    def check_capture(self):
        failed = False

        test_marker: rd.DrawcallDescription = self.find_draw("draw")
        while test_marker is not None:
            drawcall = test_marker.next
            event_name = test_marker.name
            test_marker: rd.DrawcallDescription = self.find_draw(
                "draw", drawcall.eventId)

            self.controller.SetFrameEvent(drawcall.eventId, False)
            pipe: rd.PipeState = self.controller.GetPipelineState()

            # Debug the shader
            trace: rd.ShaderDebugTrace = self.controller.DebugPixel(
                200, 150, rd.ReplayController.NoPreference,
                rd.ReplayController.NoPreference)
            if trace.debugger is None:
                failed = True
                rdtest.log.error(
                    "Test {} could not be debugged.".format(event_name))
                continue

            cycles, variables = self.process_trace(trace)

            output = self.find_output_source_var(trace,
                                                 rd.ShaderBuiltin.ColorOutput,
                                                 0)

            debugged = self.evaluate_source_var(output, variables)

            try:
                self.check_pixel_value(pipe.GetOutputTargets()[0].resourceId,
                                       200, 150, debugged.value.f32v[0:4])
            except rdtest.TestFailureException as ex:
                failed = True
                rdtest.log.error("Test {} did not match. {}".format(
                    event_name, str(ex)))
                continue
            finally:
                self.controller.FreeTrace(trace)

            rdtest.log.success(
                "Test {} matched as expected".format(event_name))

        if failed:
            raise rdtest.TestFailureException(
                "Some tests were not as expected")

        rdtest.log.success("All tests matched")
Esempio n. 30
0
 def check_events(self, events, modifs, hasSecondary):
     self.check(len(modifs) == len(events), "Expected {} events, got {}".format(len(events), len(modifs)))
     # Check for consistency first. For secondary command buffers,
     # might not have all information, so don't check for consistency
     if not hasSecondary:
         self.check_modifs_consistent(modifs)
     for i in range(len(modifs)):
         for c in range(len(events[i])):
             expected = events[i][c][1]
             actual = events[i][c][0](modifs[i])
             if not rdtest.value_compare(actual, expected, eps=1.0/256.0):
                 raise rdtest.TestFailureException(
                     "eventId {}, primitiveID {}: testing {} expected {}, got {}".format(modifs[i].eventId, modifs[i].primitiveID,
                                                                         events[i][c][0].__name__,
                                                                         expected,
                                                                         actual))