def check_capture(self): id = self.get_last_draw().copyDestination tex_details = self.get_texture(id) self.controller.SetFrameEvent(self.get_last_draw().eventId, True) data = self.controller.GetTextureData(id, rd.Subresource(0, 0, 0)) first_pixel = struct.unpack_from("BBBB", data, 0) val = [255, 0, 255, 255] if not rdtest.value_compare(first_pixel, val): raise rdtest.TestFailureException( "First pixel should be clear color {}, not {}".format( val, first_pixel)) magic_pixel = struct.unpack_from("BBBB", data, (50 * tex_details.width + 320) * 4) # allow 127 or 128 for alpha val = [0, 0, 255, magic_pixel[3]] if not rdtest.value_compare(magic_pixel, val) or magic_pixel[3] not in [127, 128]: raise rdtest.TestFailureException( "Pixel @ 320,50 should be blue: {}, not {}".format( val, magic_pixel)) rdtest.log.success("Decoded pixels from texture data are correct") img_path = rdtest.get_tmp_path('preserved_alpha.png') self.controller.SetFrameEvent(self.get_last_draw().eventId, True) save_data = rd.TextureSave() save_data.resourceId = id save_data.destType = rd.FileType.PNG save_data.alpha = rd.AlphaMapping.Discard # this should not discard the alpha self.controller.SaveTexture(save_data, img_path) data = rdtest.png_load_data(img_path) magic_pixel = struct.unpack_from("BBBB", data[-1 - 50], 320 * 4) val = [0, 0, 255, magic_pixel[3]] if not rdtest.value_compare(magic_pixel, val) or magic_pixel[3] not in [127, 128]: raise rdtest.TestFailureException( "Pixel @ 320,50 should be blue: {}, not {}".format( val, magic_pixel)) draw = self.find_draw("Draw") self.controller.SetFrameEvent(draw.eventId, False) postvs_data = self.get_postvs(draw, rd.MeshDataStage.VSOut, 0, draw.numIndices) postvs_ref = { 0: { 'vtx': 0, 'idx': 0, 'gl_Position': [-0.5, -0.5, 0.0, 1.0], 'v2fcol': [0.0, 1.0, 0.0, 1.0], }, 1: { 'vtx': 1, 'idx': 1, 'gl_Position': [0.0, 0.5, 0.0, 1.0], 'v2fcol': [0.0, 1.0, 0.0, 1.0], }, 2: { 'vtx': 2, 'idx': 2, 'gl_Position': [0.5, -0.5, 0.0, 1.0], 'v2fcol': [0.0, 1.0, 0.0, 1.0], }, } self.check_mesh_data(postvs_ref, postvs_data) results = self.controller.FetchCounters([ rd.GPUCounter.RasterizedPrimitives, rd.GPUCounter.VSInvocations, rd.GPUCounter.FSInvocations ]) results = [r for r in results if r.eventId == draw.eventId] if len(results) != 3: raise rdtest.TestFailureException( "Expected 3 results, got {} results".format(len(results))) for r in results: r: rd.CounterResult val = r.value.u32 if r.counter == rd.GPUCounter.RasterizedPrimitives: if not rdtest.value_compare(val, 1): raise rdtest.TestFailureException( "RasterizedPrimitives result {} is not as expected". format(val)) else: rdtest.log.success( "RasterizedPrimitives result is as expected") elif r.counter == rd.GPUCounter.VSInvocations: if not rdtest.value_compare(val, 3): raise rdtest.TestFailureException( "VSInvocations result {} is not as expected".format( val)) else: rdtest.log.success("VSInvocations result is as expected") elif r.counter == rd.GPUCounter.FSInvocations: if val < int(0.1 * tex_details.width * tex_details.height): raise rdtest.TestFailureException( "FSInvocations result {} is not as expected".format( val)) else: rdtest.log.success("FSInvocations result is as expected") else: raise rdtest.TestFailureException( "Unexpected counter result {}".format(r.counter)) rdtest.log.success("Counter data retrieved successfully") draw = self.find_draw("NoScissor") self.check(draw is not None) draw = draw.next pipe: rd.PipeState = self.controller.GetPipelineState() tex = rd.TextureDisplay() tex.overlay = rd.DebugOverlay.Drawcall tex.resourceId = pipe.GetOutputTargets()[0].resourceId out: rd.ReplayOutput = self.controller.CreateOutput( rd.CreateHeadlessWindowingData(100, 100), rd.ReplayOutputType.Texture) out.SetTextureDisplay(tex) out.Display() overlay_id = out.GetDebugOverlayTexID() v = pipe.GetViewport(0) self.check_pixel_value(overlay_id, int(0.5 * v.width), int(0.5 * v.height), [0.8, 0.1, 0.8, 1.0], eps=1.0 / 256.0) out.Shutdown() rdtest.log.success("Overlay color is as expected")
def check_capture(self): id = self.get_last_draw().copyDestination tex_details = self.get_texture(id) self.controller.SetFrameEvent(self.get_last_draw().eventId, True) data = self.controller.GetTextureData(id, rd.Subresource(0, 0, 0)) first_pixel = struct.unpack_from("BBBB", data, 0) val = [255, 0, 255, 255] if not rdtest.value_compare(first_pixel, val): raise rdtest.TestFailureException( "First pixel should be clear color {}, not {}".format( val, first_pixel)) magic_pixel = struct.unpack_from("BBBB", data, (50 * tex_details.width + 320) * 4) # allow 127 or 128 for alpha val = [0, 0, 255, magic_pixel[3]] if not rdtest.value_compare(magic_pixel, val) or magic_pixel[3] not in [127, 128]: raise rdtest.TestFailureException( "Pixel @ 320,50 should be blue: {}, not {}".format( val, magic_pixel)) rdtest.log.success("Decoded pixels from texture data are correct") img_path = rdtest.get_tmp_path('preserved_alpha.png') self.controller.SetFrameEvent(self.get_last_draw().eventId, True) save_data = rd.TextureSave() save_data.resourceId = id save_data.destType = rd.FileType.PNG save_data.alpha = rd.AlphaMapping.Discard # this should not discard the alpha self.controller.SaveTexture(save_data, img_path) data = rdtest.png_load_data(img_path) magic_pixel = struct.unpack_from("BBBB", data[-1 - 50], 320 * 4) val = [0, 0, 255, magic_pixel[3]] if not rdtest.value_compare(magic_pixel, val) or magic_pixel[3] not in [127, 128]: raise rdtest.TestFailureException( "Pixel @ 320,50 should be blue: {}, not {}".format( val, magic_pixel)) draw = self.find_draw("Draw") self.controller.SetFrameEvent(draw.eventId, False) postvs_data = self.get_postvs(rd.MeshDataStage.VSOut, 0, draw.numIndices) postvs_ref = { 0: { 'vtx': 0, 'idx': 0, 'gl_Position': [-0.5, -0.5, 0.0, 1.0], 'v2fcol': [1.0, 0.0, 0.0, 1.0], }, 1: { 'vtx': 1, 'idx': 1, 'gl_Position': [0.0, 0.5, 0.0, 1.0], 'v2fcol': [0.0, 1.0, 0.0, 1.0], }, 2: { 'vtx': 2, 'idx': 2, 'gl_Position': [0.5, -0.5, 0.0, 1.0], 'v2fcol': [0.0, 0.0, 1.0, 1.0], }, } self.check_mesh_data(postvs_ref, postvs_data) results = self.controller.FetchCounters([ rd.GPUCounter.RasterizedPrimitives, rd.GPUCounter.VSInvocations, rd.GPUCounter.FSInvocations ]) results = [r for r in results if r.eventId == draw.eventId] if len(results) != 3: raise rdtest.TestFailureException( "Expected 3 results, got {} results".format(len(results))) for r in results: r: rd.CounterResult val = r.value.u32 if r.counter == rd.GPUCounter.RasterizedPrimitives: if not rdtest.value_compare(val, 1): raise rdtest.TestFailureException( "RasterizedPrimitives result {} is not as expected". format(val)) else: rdtest.log.success( "RasterizedPrimitives result is as expected") elif r.counter == rd.GPUCounter.VSInvocations: if not rdtest.value_compare(val, 3): raise rdtest.TestFailureException( "VSInvocations result {} is not as expected".format( val)) else: rdtest.log.success("VSInvocations result is as expected") elif r.counter == rd.GPUCounter.FSInvocations: if val < int(0.1 * tex_details.width * tex_details.height): raise rdtest.TestFailureException( "FSInvocations result {} is not as expected".format( val)) else: rdtest.log.success("FSInvocations result is as expected") else: raise rdtest.TestFailureException( "Unexpected counter result {}".format(r.counter)) rdtest.log.success("Counter data retrieved successfully")
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")