Exemplo n.º 1
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))
Exemplo n.º 2
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")
Exemplo n.º 3
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")
Exemplo n.º 4
0
    def check_overlay(self, eventId: int, out: rd.ReplayOutput, tex: rd.TextureDisplay, save_data: rd.TextureSave):
        pipe: rd.PipeState = self.controller.GetPipelineState()

        # Check that the highlight draw overlay is empty
        tex.resourceId = pipe.GetOutputTargets()[0].resourceId

        out.SetTextureDisplay(tex)

        overlay_path = rdtest.get_tmp_path(str(self.overlay_idx) + '_draw.png')
        ref_path = self.get_ref_path(str(self.overlay_idx) + '_draw.png')

        save_data.resourceId = out.GetDebugOverlayTexID()

        self.controller.SaveTexture(save_data, overlay_path)

        if not rdtest.png_compare(overlay_path, ref_path):
            raise rdtest.TestFailureException("Reference and output image differ @ EID {}".format(str(eventId)),
                                              ref_path, overlay_path)

        self.overlay_idx = self.overlay_idx + 1
Exemplo n.º 5
0
    def check_capture(self):
        out: rd.ReplayOutput = self.controller.CreateOutput(rd.CreateHeadlessWindowingData(100, 100), rd.ReplayOutputType.Texture)

        self.check(out is not None)

        test_marker: rd.DrawcallDescription = self.find_draw("Test")

        self.controller.SetFrameEvent(test_marker.next.eventId, True)

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

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

        # Check the actual output is as expected first.

        # Background around the outside
        self.check_pixel_value(tex.resourceId, 0.1, 0.1, [0.2, 0.2, 0.2, 1.0])
        self.check_pixel_value(tex.resourceId, 0.8, 0.1, [0.2, 0.2, 0.2, 1.0])
        self.check_pixel_value(tex.resourceId, 0.5, 0.95, [0.2, 0.2, 0.2, 1.0])

        # Large dark grey triangle
        self.check_pixel_value(tex.resourceId, 0.5, 0.1, [0.1, 0.1, 0.1, 1.0])
        self.check_pixel_value(tex.resourceId, 0.5, 0.9, [0.1, 0.1, 0.1, 1.0])
        self.check_pixel_value(tex.resourceId, 0.2, 0.9, [0.1, 0.1, 0.1, 1.0])
        self.check_pixel_value(tex.resourceId, 0.8, 0.9, [0.1, 0.1, 0.1, 1.0])

        # Red upper half triangle
        self.check_pixel_value(tex.resourceId, 0.3, 0.4, [1.0, 0.0, 0.0, 1.0])
        # Blue lower half triangle
        self.check_pixel_value(tex.resourceId, 0.3, 0.6, [0.0, 0.0, 1.0, 1.0])

        # Floating clipped triangle
        self.check_pixel_value(tex.resourceId, 335, 140, [0.0, 0.0, 0.0, 1.0])
        self.check_pixel_value(tex.resourceId, 340, 140, [0.2, 0.2, 0.2, 1.0])

        # Triangle size triangles
        self.check_pixel_value(tex.resourceId, 200, 51, [1.0, 0.5, 1.0, 1.0])
        self.check_pixel_value(tex.resourceId, 200, 65, [1.0, 1.0, 0.0, 1.0])
        self.check_pixel_value(tex.resourceId, 200, 79, [0.0, 1.0, 1.0, 1.0])
        self.check_pixel_value(tex.resourceId, 200, 93, [0.0, 1.0, 0.0, 1.0])

        for overlay in rd.DebugOverlay:
            if overlay == rd.DebugOverlay.NoOverlay:
                continue

            # These overlays are just displaymodes really, not actually separate overlays
            if overlay == rd.DebugOverlay.NaN or overlay == rd.DebugOverlay.Clipping:
                continue

            # Unfortunately line-fill rendering seems to vary too much by IHV, so gives inconsistent results
            if overlay == rd.DebugOverlay.Wireframe:
                continue

            tex.overlay = overlay
            out.SetTextureDisplay(tex)

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

            save_data = rd.TextureSave()
            save_data.resourceId = out.GetDebugOverlayTexID()
            save_data.destType = rd.FileType.PNG

            save_data.comp.blackPoint = 0.0
            save_data.comp.whitePoint = 1.0

            tolerance = 2

            # These overlays return grayscale above 1, so rescale to an expected range.
            if (overlay == rd.DebugOverlay.QuadOverdrawDraw or overlay == rd.DebugOverlay.QuadOverdrawPass or
                    overlay == rd.DebugOverlay.TriangleSizeDraw or overlay == rd.DebugOverlay.TriangleSizePass):
                save_data.comp.whitePoint = 10.0

            # These overlays modify the underlying texture, so we need to save it out instead of the overlay
            if overlay == rd.DebugOverlay.ClearBeforeDraw or overlay == rd.DebugOverlay.ClearBeforePass:
                save_data.resourceId = tex.resourceId

            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(str(overlay)), overlay_path, ref_path)

            rdtest.log.success("Reference and output image are identical for {}".format(str(overlay)))

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

        tmp_path = rdtest.get_tmp_path('depth.png')
        ref_path = self.get_ref_path('depth.png')

        self.controller.SaveTexture(save_data, tmp_path)

        if not rdtest.png_compare(tmp_path, ref_path):
            raise rdtest.TestFailureException("Reference and output image differ for depth {}", tmp_path, ref_path)

        rdtest.log.success("Reference and output image are identical for depth")

        save_data.channelExtract = 1

        tmp_path = rdtest.get_tmp_path('stencil.png')
        ref_path = self.get_ref_path('stencil.png')

        self.controller.SaveTexture(save_data, tmp_path)

        if not rdtest.png_compare(tmp_path, ref_path):
            raise rdtest.TestFailureException("Reference and output image differ for stencil {}", tmp_path, ref_path)

        rdtest.log.success("Reference and output image are identical for stencil")

        self.check_clearbeforedraw_depth(out, pipe.GetDepthTarget().resourceId)

        out.Shutdown()
Exemplo n.º 6
0
    def check_capture(self):
        action: rd.ActionDescription = self.find_action("Degenerate")
        self.controller.SetFrameEvent(action.next.eventId, True)
        pipe: rd.VKState = self.controller.GetVulkanPipelineState()

        if pipe.multisample.rasterSamples != 4:
            raise rdtest.TestFailureException("MSAA sample count is {}, not 1".format(pipe.multisample.rasterSamples))

        sampleLoc: rd.VKSampleLocations = pipe.multisample.sampleLocations

        if sampleLoc.gridWidth != 1:
            raise rdtest.TestFailureException("Sample locations grid width is {}, not 1".format(sampleLoc.gridWidth))
        if sampleLoc.gridHeight != 1:
            raise rdtest.TestFailureException("Sample locations grid height is {}, not 1".format(sampleLoc.gridHeight))

        # [0] and [1] should be identical, as should [2] and [3], but they should be different from each other
        if not sampleLoc.customLocations[0] == sampleLoc.customLocations[1]:
            raise rdtest.TestFailureException("In degenerate case, sample locations [0] and [1] don't match: {} vs {}"
                                              .format(sampleLoc.customLocations[0], sampleLoc.customLocations[1]))

        if not sampleLoc.customLocations[2] == sampleLoc.customLocations[3]:
            raise rdtest.TestFailureException("In degenerate case, sample locations [2] and [3] don't match: {} vs {}"
                                              .format(sampleLoc.customLocations[2], sampleLoc.customLocations[3]))

        if sampleLoc.customLocations[1] == sampleLoc.customLocations[2]:
            raise rdtest.TestFailureException("In degenerate case, sample locations [1] and [2] DO match: {} vs {}"
                                              .format(sampleLoc.customLocations[1], sampleLoc.customLocations[2]))

        action: rd.ActionDescription = self.find_action("Rotated")
        self.controller.SetFrameEvent(action.next.eventId, True)
        pipe: rd.VKState = self.controller.GetVulkanPipelineState()

        if pipe.multisample.rasterSamples != 4:
            raise rdtest.TestFailureException("MSAA sample count is {}, not 1".format(pipe.multisample.rasterSamples))

        sampleLoc: rd.VKSampleLocations = pipe.multisample.sampleLocations

        if sampleLoc.gridWidth != 1:
            raise rdtest.TestFailureException("Sample locations grid width is {}, not 1".format(sampleLoc.gridWidth))
        if sampleLoc.gridHeight != 1:
            raise rdtest.TestFailureException("Sample locations grid height is {}, not 1".format(sampleLoc.gridHeight))

        # All sample locations should be unique
        if sampleLoc.customLocations[0] == sampleLoc.customLocations[1]:
            raise rdtest.TestFailureException("In rotated case, sample locations [0] and [1] DO match: {} vs {}"
                                              .format(sampleLoc.customLocations[0], sampleLoc.customLocations[1]))

        if sampleLoc.customLocations[1] == sampleLoc.customLocations[2]:
            raise rdtest.TestFailureException("In rotated case, sample locations [1] and [2] DO match: {} vs {}"
                                              .format(sampleLoc.customLocations[1], sampleLoc.customLocations[2]))

        if sampleLoc.customLocations[2] == sampleLoc.customLocations[3]:
            raise rdtest.TestFailureException("In rotated case, sample locations [2] and [3] DO match: {} vs {}"
                                              .format(sampleLoc.customLocations[2], sampleLoc.customLocations[3]))

        rdtest.log.success("Pipeline state is correct")

        # Grab the multisampled image's ID here
        save_data = rd.TextureSave()
        curpass: rd.VKCurrentPass = pipe.currentPass
        save_data.resourceId = curpass.framebuffer.attachments[curpass.renderpass.colorAttachments[0]].imageResourceId
        save_data.destType = rd.FileType.PNG
        save_data.sample.mapToArray = False

        dim = (0, 0)
        fmt: rd.ResourceFormat = None
        texs = self.controller.GetTextures()
        for tex in texs:
            tex: rd.TextureDescription
            if tex.resourceId == save_data.resourceId:
                dim = (tex.width, tex.height)
                fmt = tex.format

        if dim == (0,0):
            raise rdtest.TestFailureException("Couldn't get dimensions of texture")

        halfdim = (dim[0] >> 1, dim[1])

        if (fmt.type != rd.ResourceFormatType.Regular or fmt.compByteWidth != 1 or fmt.compCount != 4):
            raise rdtest.TestFailureException("Texture is not RGBA8 as expected: {}".format(fmt.Name()))

        stride = fmt.compByteWidth * fmt.compCount * dim[0]

        last_action: rd.ActionDescription = self.get_last_action()

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

        # Due to the variability of rasterization between implementations or even drivers,
        # we don't want to check against a 'known good'.
        # So instead we verify that at the first degenerate action each pair of two sample's images are identical and that
        # in the rotated grid case each sample's image is distinct.
        # In future we could also check that the degenerate case 'stretches' the triangle up, as with the way the
        # geometry is defined the second sample image should be a superset (i.e. strictly more samples covered).
        rotated_paths = []
        degenerate_paths = []

        for sample in range(0, 4):
            tmp_path = rdtest.get_tmp_path('sample{}.png'.format(sample))
            degenerate_path = rdtest.get_tmp_path('degenerate{}.png'.format(sample))
            rotated_path = rdtest.get_tmp_path('rotated{}.png'.format(sample))

            rotated_paths.append(rotated_path)
            degenerate_paths.append(degenerate_path)

            save_data.sample.sampleIndex = sample
            self.controller.SaveTexture(save_data, tmp_path)

            combined_data = rdtest.png_load_data(tmp_path)

            # crop left for degenerate, and crop right for rotated
            degenerate = []
            rotated = []
            for row in range(0, dim[1]):
                srcstart = row * stride

                len = halfdim[0] * fmt.compCount

                degenerate.append(combined_data[row][0:len])
                rotated.append(combined_data[row][len:])

            rdtest.png_save(degenerate_path, degenerate, halfdim, True)
            rdtest.png_save(rotated_path, rotated, halfdim, True)

        # first two degenerate images should be identical, as should the last two, and they should be different.
        if not rdtest.png_compare(degenerate_paths[0], degenerate_paths[1], 0):
            raise rdtest.TestFailureException("Degenerate grid sample 0 and 1 are different",
                                              degenerate_paths[0], degenerate_paths[1])

        if not rdtest.png_compare(degenerate_paths[2], degenerate_paths[3], 0):
            raise rdtest.TestFailureException("Degenerate grid sample 2 and 3 are different",
                                              degenerate_paths[2], degenerate_paths[3])

        if rdtest.png_compare(degenerate_paths[1], degenerate_paths[2], 0):
            raise rdtest.TestFailureException("Degenerate grid sample 1 and 2 are identical",
                                              degenerate_paths[1], degenerate_paths[2])

        rdtest.log.success("Degenerate grid sample images are as expected")

        # all rotated images should be different
        for A in range(0, 4):
            for B in range(A+1, 4):
                if rdtest.png_compare(rotated_paths[A], rotated_paths[B], 0):
                    raise rdtest.TestFailureException("Rotated grid sample {} and {} are identical".format(A, B),
                                                      rotated_paths[A], rotated_paths[B])

        rdtest.log.success("Rotated grid sample images are as expected")
Exemplo n.º 7
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)

        tex = rd.TextureDisplay()

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

            if draw.flags & rd.DrawFlags.Drawcall:
                tex.resourceId = self.controller.GetPipelineState(
                ).GetOutputTargets()[0].resourceId
                out.SetTextureDisplay(tex)

                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.resourceId).height - y

                picked: rd.PixelValue = out.PickPixel(tex.resourceId, False, x,
                                                      y, 0, 0, 0)

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

            draw = draw.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.resourceId
        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")

        out.Shutdown()