Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/rdc/commands/descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ def _table() -> None:
r.get("format", "-"),
r.get("width", "-"),
r.get("height", "-"),
r.get("depth", "-"),
]
for r in rows
]
Expand All @@ -85,6 +86,7 @@ def _table() -> None:
"FORMAT",
"WIDTH",
"HEIGHT",
"DEPTH",
],
no_header=no_header,
)
Expand Down
3 changes: 2 additions & 1 deletion src/rdc/commands/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,12 +139,13 @@ def _table() -> None:
r.get("name", "-"),
r.get("width", "-"),
r.get("height", "-"),
r.get("depth", "-"),
r.get("format", "-"),
r.get("size", "-"),
]
for r in rows
]
header = ["ID", "TYPE", "NAME", "WIDTH", "HEIGHT", "FORMAT", "SIZE"]
header = ["ID", "TYPE", "NAME", "WIDTH", "HEIGHT", "DEPTH", "FORMAT", "SIZE"]
write_tsv(tsv_rows, header=header, no_header=no_header)

render_list(
Expand Down
3 changes: 3 additions & 0 deletions src/rdc/handlers/descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ def _handle_descriptors(
if tex is not None:
d_row["width"] = tex.width
d_row["height"] = tex.height
d_row["depth"] = getattr(tex, "depth", 1)
d_row["dimension"] = getattr(tex, "dimension", 0)
d_row["texture_type"] = _enum_name(getattr(tex, "type", ""))
if type_name in ("Sampler", "ImageSampler"):
s = getattr(ud, "sampler", None)
if s is not None:
Expand Down
3 changes: 3 additions & 0 deletions src/rdc/handlers/query.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,9 @@ def enrich_resource_row(row: dict[str, Any], state: DaemonState) -> dict[str, An
fmt = getattr(tex, "format", None)
row["width"] = tex.width
row["height"] = tex.height
row["depth"] = getattr(tex, "depth", 1)
row["dimension"] = getattr(tex, "dimension", 0)
row["texture_type"] = _enum_name(getattr(tex, "type", ""))
row["format"] = fmt.Name() if fmt is not None and hasattr(fmt, "Name") else ""
row["size"] = getattr(tex, "byteSize", 0)
return row
Expand Down
7 changes: 5 additions & 2 deletions src/rdc/handlers/texture.py
Original file line number Diff line number Diff line change
Expand Up @@ -332,9 +332,12 @@ def _handle_tex_stats(
return _error_response(
request_id, -32001, f"mip {mip} out of range (max: {tex.mips - 1})"
), True
if array_slice < 0 or array_slice >= tex.arraysize:
slice_count = tex.arraysize
if tex.type == rd.TextureType.Texture3D:
slice_count = max(1, tex.depth >> mip)
if array_slice < 0 or array_slice >= slice_count:
return _error_response(
request_id, -32001, f"slice {array_slice} out of range (max: {tex.arraysize - 1})"
request_id, -32001, f"slice {array_slice} out of range (max: {slice_count - 1})"
), True

sub = rd.Subresource()
Expand Down
5 changes: 5 additions & 0 deletions tests/unit/test_descriptors_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ def _result() -> dict[str, Any]:
"format": "BC1_SRGB",
"width": 512,
"height": 512,
"depth": 4,
"dimension": 3,
"texture_type": "Texture3D",
}
],
}
Expand All @@ -38,6 +41,8 @@ def test_descriptors_table(monkeypatch) -> None:
assert "g_textures" in res.output
assert "BC1_SRGB" in res.output
assert "512" in res.output
assert "DEPTH" in res.output
assert "\t4\n" in res.output


def test_descriptors_binding_filter_forwarded(monkeypatch) -> None:
Expand Down
15 changes: 12 additions & 3 deletions tests/unit/test_descriptors_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,13 @@ def test_descriptors_binding_name_correlation() -> None:
state.res_names = {371: "2D Image 371"}
state.tex_map = {
371: SimpleNamespace(
width=512, height=512, format=SimpleNamespace(Name=lambda: "BC1_SRGB"), byteSize=174776
width=64,
height=64,
depth=4,
dimension=3,
type=rd.TextureType.Texture3D,
format=SimpleNamespace(Name=lambda: "BC1_SRGB"),
byteSize=174776,
)
}
d = _call(state, "descriptors", eid=16)["result"]["descriptors"][0]
Expand All @@ -232,8 +238,11 @@ def test_descriptors_binding_name_correlation() -> None:
assert d["array_element"] == 46
assert d["resource_id"] == 371
assert d["resource_name"] == "2D Image 371"
assert d["width"] == 512
assert d["height"] == 512
assert d["width"] == 64
assert d["height"] == 64
assert d["depth"] == 4
assert d["dimension"] == 3
assert d["texture_type"] == "Texture3D"


def test_descriptors_binding_empty_without_reflection() -> None:
Expand Down
6 changes: 3 additions & 3 deletions tests/unit/test_formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,9 +303,9 @@ def test_resources_table(self, monkeypatch) -> None:
result = CliRunner().invoke(main, ["resources"])
assert result.exit_code == 0
assert result.output == (
"ID\tTYPE\tNAME\tWIDTH\tHEIGHT\tFORMAT\tSIZE\n"
"10\tTexture\talbedo\t-\t-\t-\t-\n"
"20\tBuffer\tverts\t-\t-\t-\t-\n"
"ID\tTYPE\tNAME\tWIDTH\tHEIGHT\tDEPTH\tFORMAT\tSIZE\n"
"10\tTexture\talbedo\t-\t-\t-\t-\t-\n"
"20\tBuffer\tverts\t-\t-\t-\t-\t-\n"
)

def test_counters_quiet(self, monkeypatch) -> None:
Expand Down
6 changes: 5 additions & 1 deletion tests/unit/test_resources_commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def test_resources_enriched_columns(monkeypatch) -> None:
"name": "2D Image 371",
"width": 512,
"height": 512,
"depth": 4,
"dimension": 3,
"texture_type": "Texture3D",
"format": "BC1_SRGB",
"size": 174776,
}
Expand All @@ -43,7 +46,8 @@ def test_resources_enriched_columns(monkeypatch) -> None:
)
result = CliRunner().invoke(resources_cmd, [])
assert result.exit_code == 0
assert "ID\tTYPE\tNAME\tWIDTH\tHEIGHT\tFORMAT\tSIZE" in result.output
assert "ID\tTYPE\tNAME\tWIDTH\tHEIGHT\tDEPTH\tFORMAT\tSIZE" in result.output
assert "\t4\tBC1_SRGB\t" in result.output
assert "512" in result.output
assert "BC1_SRGB" in result.output

Expand Down
18 changes: 18 additions & 0 deletions tests/unit/test_resources_filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,24 @@ def test_resources_list_enriched_with_dims(self) -> None:
assert row["format"] == "BC1_SRGB"
assert row["size"] == 174776

def test_texture3d_metadata_is_exposed(self) -> None:
state = _state_with_resources([_make_res(8413, "RainDropSplash01.dds", "Texture")])
state.tex_map = {
8413: rd.TextureDescription(
resourceId=rd.ResourceId(8413),
type=rd.TextureType.Texture3D,
dimension=3,
width=64,
height=64,
depth=4,
)
}
resp, _ = _handle_request(rpc_request("resource", {"id": 8413}), state)
resource = resp["result"]["resource"]
assert resource["depth"] == 4
assert resource["dimension"] == 3
assert resource["texture_type"] == "Texture3D"

def test_buffer_resource_gets_size(self) -> None:
state = _state_with_resources([_make_res(99, "vtx buffer", "Buffer")])
state.buf_map = {99: SimpleNamespace(length=4096)}
Expand Down
46 changes: 46 additions & 0 deletions tests/unit/test_tex_stats_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,52 @@ def test_tex_stats_valid_mip0_slice0() -> None:
assert resp["result"]["slice"] == 0


def _make_texture3d_state() -> DaemonState:
ctrl = rd.MockReplayController()
tex = rd.TextureDescription(
resourceId=rd.ResourceId(42),
type=rd.TextureType.Texture3D,
dimension=3,
width=64,
height=64,
depth=4,
mips=7,
arraysize=1,
)
ctrl._textures = [tex]
ctrl._actions = [
rd.ActionDescription(eventId=100, flags=rd.ActionFlags.Drawcall, _name="vkCmdDraw"),
]
return make_daemon_state(
ctrl=ctrl,
current_eid=100,
rd=rd,
tex_map={42: tex},
)


def test_tex_stats_texture3d_accepts_depth_slices_for_requested_mip() -> None:
state = _make_texture3d_state()

for mip, array_slice in ((0, 3), (1, 1), (2, 0)):
resp, _ = _handle_request(
rpc_request("tex_stats", {"id": 42, "mip": mip, "slice": array_slice}), state
)
assert resp["result"]["mip"] == mip
assert resp["result"]["slice"] == array_slice


def test_tex_stats_texture3d_rejects_slice_after_mip_depth_reduction() -> None:
state = _make_texture3d_state()

resp, _ = _handle_request(rpc_request("tex_stats", {"id": 42, "mip": 1, "slice": 2}), state)
assert resp["error"]["code"] == -32001
assert resp["error"]["message"] == "slice 2 out of range (max: 1)"

resp, _ = _handle_request(rpc_request("tex_stats", {"id": 42, "mip": 2, "slice": 1}), state)
assert resp["error"]["message"] == "slice 1 out of range (max: 0)"


# ---------------------------------------------------------------------------
# B54: histogram channel length mismatch guard
# ---------------------------------------------------------------------------
Expand Down
Loading