mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-04 17:10:47 +00:00
208 lines
7.1 KiB
ReStructuredText
208 lines
7.1 KiB
ReStructuredText
Fetch Shader details
|
|
====================
|
|
|
|
In this example we will fetch the disassembly for a shader and a set of constant values.
|
|
|
|
When disassembling a shader there may be more than one possible representation available, so we first enumerate the formats that are available using :py:meth:`~renderdoc.ReplayController.GetDisassemblyTargets` before selecting a target to disassemble to. The first target is always a reasonable default, and there will be at least one. :py:meth:`~renderdoc.ReplayController.GetDisassemblyTargets` takes a parameter indicating whether the pipeline state object will be available - some disassembly targets require the full pipeline and are not available when disassembling only a shader in isolation:
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
print("Available disassembly formats:")
|
|
|
|
targets = controller.GetDisassemblyTargets(True)
|
|
|
|
for disasm in targets:
|
|
print(" - " + disasm)
|
|
|
|
target = targets[0]
|
|
|
|
Next we fetch any ancillary data that might be needed to disassemble - this varies by API depending on whether it supports multiple entry points per shader, or has a concept of pipeline state objects that are used together with a shader to disassemble.
|
|
|
|
For the purposes of this example we use the API abstraction :py:class:`~renderdoc.PipeState` so that this code works on a capture from any API, so we fetch the state bindings that we need. Finally we fetch the disassembled shader string with :py:meth:`~renderdoc.ReplayController.DisassembleShader` and print it:
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
state = controller.GetPipelineState()
|
|
|
|
# For some APIs, it might be relevant to set the PSO id or entry point name
|
|
pipe = state.GetGraphicsPipelineObject()
|
|
entry = state.GetShaderEntryPoint(rd.ShaderStage.Pixel)
|
|
|
|
# Get the pixel shader's reflection object
|
|
ps = state.GetShaderReflection(rd.ShaderStage.Pixel)
|
|
|
|
cb = state.GetConstantBlock(rd.ShaderStage.Pixel, 0, 0)
|
|
|
|
print("Pixel shader:")
|
|
print(controller.DisassembleShader(pipe, ps.reflection, target))
|
|
|
|
Now we want to display the constants bound to this shader. Shader bindings is an area that diverges quite a lot between the APIs, and RenderDoc's abstraction over this is detailed in :ref:`more detail <descriptor-abstraction>`. For now, we'll simply select the first constant buffer in this shader and fetch the constants for it with :py:meth:`~renderdoc.ReplayController.GetCBufferVariableContents`.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
cbufferVars = controller.GetCBufferVariableContents(pipe, ps.resourceId, rd.ShaderStage.Pixel, entry, 0, cb.descriptor.resource, 0, 0)
|
|
|
|
Since constants can contain structs of other constants, we want to define a recursive function that will iterate over a constant and print it along with its value. We want to handle both vectors and matrices so we need to iterate over both rows and columns for each variable.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
def printVar(v, indent = ''):
|
|
print(indent + v.name + ":")
|
|
|
|
if len(v.members) == 0:
|
|
valstr = ""
|
|
for r in range(0, v.rows):
|
|
valstr += indent + ' '
|
|
|
|
for c in range(0, v.columns):
|
|
valstr += '%.3f ' % v.value.fv[r*v.columns + c]
|
|
|
|
if r < v.rows-1:
|
|
valstr += "\n"
|
|
|
|
print(valstr)
|
|
|
|
for v in v.members:
|
|
printVar(v, indent + ' ')
|
|
|
|
Finally, we iterate over the constants that we fetched earlier calling the function for each.
|
|
|
|
.. highlight:: python
|
|
.. code:: python
|
|
|
|
for v in cbufferVars:
|
|
printVar(v)
|
|
|
|
Example Source
|
|
--------------
|
|
|
|
.. only:: html and not htmlhelp
|
|
|
|
:download:`Download the example script <fetch_shader.py>`.
|
|
|
|
.. literalinclude:: fetch_shader.py
|
|
|
|
Sample output:
|
|
|
|
.. sourcecode:: text
|
|
|
|
Available disassembly formats:
|
|
- DXBC
|
|
- AMD GCN ISA
|
|
Pixel shader:
|
|
Shader hash 9dd8337a-c75dd787-1fa0f07e-5f39f955
|
|
|
|
ps_5_0
|
|
dcl_globalFlags refactoringAllowed
|
|
dcl_constantbuffer cb0[8], immediateIndexed
|
|
dcl_sampler gDepthSam (s0), mode_default
|
|
dcl_resource_texture2d (float,float,float,float) gDepthMap (t0)
|
|
dcl_resource_texture2d (float,float,float,float) gGBufferMap (t1)
|
|
dcl_input_ps linear v1.xyz
|
|
dcl_input_ps linear v2.xyw
|
|
dcl_output o0.xyzw
|
|
dcl_output o1.xyzw
|
|
dcl_temps 6
|
|
|
|
0: nop
|
|
1: mov r0.xyz, v2.xywx
|
|
2: div r0.xy, r0.xyxx, r0.zzzz
|
|
3: mul r0.xy, r0.xyxx, l(0.500000, -0.500000, 0.000000, 0.000000)
|
|
4: add r0.xy, r0.xyxx, l(0.500000, 0.500000, 0.000000, 0.000000)
|
|
5: mov r0.xy, r0.xyxx
|
|
6: sample_indexable(texture2d)(float,float,float,float) r0.z, r0.xyxx, gDepthMap.yzxw, gDepthSam
|
|
7: mov r0.z, r0.z
|
|
8: nop
|
|
9: mov r0.z, r0.z
|
|
10: mov r0.z, -r0.z
|
|
11: add r0.z, r0.z, l(1.001801)
|
|
12: div r0.z, l(0.421448), r0.z
|
|
13: mov r0.z, r0.z
|
|
14: dp3 r0.w, v1.xyzx, v1.xyzx
|
|
15: rsq r0.w, r0.w
|
|
16: mul r1.xyz, r0.wwww, v1.xyzx
|
|
17: div r0.z, r0.z, r1.z
|
|
18: mul r2.xyz, r0.zzzz, r1.xyzx
|
|
19: sample_indexable(texture2d)(float,float,float,float) r0.xyzw, r0.xyxx, gGBufferMap.xyzw, gDepthSam
|
|
20: dp3 r1.w, r0.xyzx, r0.xyzx
|
|
21: rsq r1.w, r1.w
|
|
22: mul r0.xyz, r0.xyzx, r1.wwww
|
|
23: mov r3.xyz, gLightPosV.xyzx
|
|
24: mov r4.xyz, -r2.xyzx
|
|
25: add r4.xyz, r3.xyzx, r4.xyzx
|
|
26: dp3 r1.w, r4.xyzx, r4.xyzx
|
|
27: rsq r1.w, r1.w
|
|
28: mul r4.xyz, r1.wwww, r4.xyzx
|
|
29: dp3 r1.w, r0.xyzx, r4.xyzx
|
|
30: max r5.x, r1.w, l(0)
|
|
31: nop
|
|
32: mov r1.xyz, -r1.xyzx
|
|
33: add r1.xyz, r1.xyzx, r4.xyzx
|
|
34: dp3 r1.w, r1.xyzx, r1.xyzx
|
|
35: rsq r1.w, r1.w
|
|
36: mul r1.xyz, r1.wwww, r1.xyzx
|
|
37: mov r0.xyz, r0.xyzx
|
|
38: mul r0.w, r0.w, l(64.000000)
|
|
39: dp3 r0.x, r1.xyzx, r0.xyzx
|
|
40: max r0.x, r0.x, l(0)
|
|
41: log r0.x, r0.x
|
|
42: mul r0.x, r0.x, r0.w
|
|
43: exp r5.y, r0.x
|
|
44: mov r5.y, r5.y
|
|
45: nop
|
|
46: mov r3.xyz, r3.xyzx
|
|
47: mov r2.xyz, r2.xyzx
|
|
48: mov r0.xyz, gLight.att.xyzx
|
|
49: mov r1.xyz, -r2.xyzx
|
|
50: add r1.xyz, r1.xyzx, r3.xyzx
|
|
51: dp3 r0.w, r1.xyzx, r1.xyzx
|
|
52: sqrt r0.w, r0.w
|
|
53: mul r0.y, r0.y, r0.w
|
|
54: add r0.x, r0.y, r0.x
|
|
55: mul r0.y, r0.w, r0.w
|
|
56: mul r0.y, r0.z, r0.y
|
|
57: add r0.x, r0.y, r0.x
|
|
58: div r0.x, l(1.000000), r0.x
|
|
59: mov r0.x, r0.x
|
|
60: mul r0.xy, r5.xyxx, r0.xxxx
|
|
61: max r0.xy, r0.xyxx, l(0, 0, 0, 0)
|
|
62: mul o0.xyzw, r0.xxxx, gLight.diffuse.xyzw
|
|
63: mul o1.xyzw, r0.yyyy, gLight.diffuse.xyzw
|
|
64: ret
|
|
|
|
gLight:
|
|
pos:
|
|
-2.022 2.000 -3.694
|
|
dir:
|
|
0.000 0.000 0.000
|
|
ambient:
|
|
0.300 0.300 0.300 1.000
|
|
diffuse:
|
|
0.300 1.000 0.600 1.000
|
|
spec:
|
|
0.500 0.500 0.500 1.000
|
|
att:
|
|
0.000 0.200 0.100
|
|
spotPower:
|
|
0.000
|
|
range:
|
|
3.000
|
|
gLightPosV:
|
|
-2.022 0.200 6.306 -107374176.000
|
|
gLigthDirES:
|
|
-0.298 -0.596 -0.745
|
|
gWorldViewProj:
|
|
1.567 0.000 0.000 0.000
|
|
0.000 2.414 0.000 0.000
|
|
0.000 0.000 1.002 1.000
|
|
-3.169 0.483 5.896 6.306
|
|
gWorldView:
|
|
1.000 0.000 0.000 0.000
|
|
0.000 1.000 0.000 0.000
|
|
0.000 0.000 1.000 0.000
|
|
-2.022 0.200 6.306 1.000
|