From 665ad6c05c4adb9034fd165fa5893926e7979d6c Mon Sep 17 00:00:00 2001 From: Steve Karolewics Date: Sat, 27 Jul 2019 14:36:02 -0700 Subject: [PATCH] Move D3D11 API usage out of dxbc_debug.cpp The following instructions used D3D11 calls to compute results, and have been moved to an API wrapper class that is defined in d3d11_shaderdebug.cpp: transcendentals (rcp, rsqrt, exp2, log2, and sincos), sample info/pos, bufinfo, resinfo, and sample/load/gather/lod. --- renderdoc/driver/d3d11/d3d11_shaderdebug.cpp | 1377 +++++++++++++++- renderdoc/driver/shaders/dxbc/dxbc_debug.cpp | 1468 ++---------------- renderdoc/driver/shaders/dxbc/dxbc_debug.h | 56 +- 3 files changed, 1524 insertions(+), 1377 deletions(-) diff --git a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp index b1de81d6b..b31967b67 100644 --- a/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp +++ b/renderdoc/driver/d3d11/d3d11_shaderdebug.cpp @@ -27,6 +27,7 @@ #include "driver/d3d11/d3d11_renderstate.h" #include "driver/d3d11/d3d11_resources.h" #include "driver/shaders/dxbc/dxbc_debug.h" +#include "driver/shaders/dxbc/dxbc_disassemble.h" #include "maths/formatpacking.h" #include "maths/vec.h" #include "strings/string_utils.h" @@ -239,6 +240,1368 @@ static void FlattenVariables(const rdcarray &constants, FlattenVariables(constants, invars, outvars, "", 0); } +class D3D11DebugAPIWrapper : public ShaderDebug::DebugAPIWrapper +{ +public: + D3D11DebugAPIWrapper(WrappedID3D11Device *device, DXBC::DXBCFile *dxbc, + const ShaderDebug::GlobalState &globalState); + + void SetCurrentInstruction(uint32_t instruction) { m_instruction = instruction; } + void AddDebugMessage(MessageCategory c, MessageSeverity sv, MessageSource src, std::string d); + + bool CalculateMathIntrinsic(DXBC::OpcodeType opcode, const ShaderVariable &input, + ShaderVariable &output1, ShaderVariable &output2); + + ShaderVariable GetSampleInfo(DXBC::OperandType type, bool isAbsoluteResource, UINT slot, + const char *opString); + ShaderVariable GetBufferInfo(DXBC::OperandType type, UINT slot, const char *opString); + ShaderVariable GetResourceInfo(DXBC::OperandType type, UINT slot, uint32_t mipLevel, int &dim); + + bool CalculateSampleGather(DXBC::OpcodeType opcode, + ShaderDebug::SampleGatherResourceData resourceData, + ShaderDebug::SampleGatherSamplerData samplerData, ShaderVariable uv, + ShaderVariable ddxCalc, ShaderVariable ddyCalc, + const int texelOffsets[3], int multisampleIndex, float lodOrCompareValue, + const uint8_t swizzle[4], ShaderDebug::GatherChannel gatherChannel, + const char *opString, ShaderVariable &output); + +private: + D3D11_ShaderType GetShaderType() { return m_dxbc ? m_dxbc->m_Type : D3D11_ShaderType_Pixel; } + WrappedID3D11Device *m_pDevice; + DXBC::DXBCFile *m_dxbc; + const ShaderDebug::GlobalState &m_globalState; + uint32_t m_instruction; +}; + +D3D11DebugAPIWrapper::D3D11DebugAPIWrapper(WrappedID3D11Device *device, DXBC::DXBCFile *dxbc, + const ShaderDebug::GlobalState &globalState) + : m_pDevice(device), m_dxbc(dxbc), m_globalState(globalState), m_instruction(0) +{ +} + +void D3D11DebugAPIWrapper::AddDebugMessage(MessageCategory c, MessageSeverity sv, MessageSource src, + std::string d) +{ + m_pDevice->AddDebugMessage(c, sv, src, d); +} + +ShaderVariable D3D11DebugAPIWrapper::GetSampleInfo(DXBC::OperandType type, bool isAbsoluteResource, + UINT slot, const char *opString) +{ + ID3D11DeviceContext *context = NULL; + m_pDevice->GetImmediateContext(&context); + + ShaderVariable result("", 0U, 0U, 0U, 0U); + + ID3D11Resource *res = NULL; + + if(type == DXBC::TYPE_RASTERIZER) + { + ID3D11RenderTargetView *rtv[8] = {}; + ID3D11DepthStencilView *dsv = NULL; + + context->OMGetRenderTargets(8, rtv, &dsv); + + // try depth first - both should match sample count though to be valid + if(dsv) + { + dsv->GetResource(&res); + } + else + { + for(size_t i = 0; i < ARRAY_COUNT(rtv); i++) + { + if(rtv[i]) + { + rtv[i]->GetResource(&res); + break; + } + } + } + + if(!res) + { + RDCWARN("No targets bound for output when calling sampleinfo on rasterizer"); + + m_pDevice->AddDebugMessage( + MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\n" + "No targets bound for output when calling sampleinfo on rasterizer", + m_instruction, opString)); + } + + for(size_t i = 0; i < ARRAY_COUNT(rtv); i++) + SAFE_RELEASE(rtv[i]); + SAFE_RELEASE(dsv); + } + else if(type == DXBC::TYPE_RESOURCE && isAbsoluteResource) + { + ID3D11ShaderResourceView *srv = NULL; + switch(GetShaderType()) + { + case D3D11_ShaderType_Vertex: context->VSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Hull: context->HSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Domain: context->DSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Geometry: context->GSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Pixel: context->PSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Compute: context->CSGetShaderResources(slot, 1, &srv); break; + } + + if(srv) + { + srv->GetResource(&res); + } + else + { + RDCWARN("SRV is NULL being queried by sampleinfo"); + + m_pDevice->AddDebugMessage( + MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\nSRV is NULL being queried by sampleinfo", + m_instruction, opString)); + } + + SAFE_RELEASE(srv); + } + else + { + RDCWARN("unexpected operand type to sample_info"); + } + + if(res) + { + D3D11_RESOURCE_DIMENSION dim = D3D11_RESOURCE_DIMENSION_UNKNOWN; + res->GetType(&dim); + + if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) + { + D3D11_TEXTURE2D_DESC desc; + ((ID3D11Texture2D *)res)->GetDesc(&desc); + + // returns 1 for non-multisampled resources + result.value.u.x = RDCMAX(1U, desc.SampleDesc.Count); + } + else + { + if(type == DXBC::TYPE_RASTERIZER) + { + // special behaviour for non-2D (i.e. by definition non-multisampled) textures when + // querying the rasterizer, just return 1. + result.value.u.x = 1; + } + else + { + m_pDevice->AddDebugMessage( + MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\nResource specified is not a 2D texture", + m_instruction, opString)); + + result.value.u.x = 0; + } + } + + SAFE_RELEASE(res); + } + SAFE_RELEASE(context); + return result; +} + +ShaderVariable D3D11DebugAPIWrapper::GetBufferInfo(DXBC::OperandType type, UINT slot, + const char *opString) +{ + ID3D11DeviceContext *context = NULL; + m_pDevice->GetImmediateContext(&context); + + ShaderVariable result("", 0U, 0U, 0U, 0U); + + if(type == DXBC::TYPE_UNORDERED_ACCESS_VIEW) + { + ID3D11UnorderedAccessView *uav = NULL; + if(GetShaderType() == D3D11_ShaderType_Compute) + context->CSGetUnorderedAccessViews(slot, 1, &uav); + else + context->OMGetRenderTargetsAndUnorderedAccessViews(0, NULL, NULL, slot, 1, &uav); + + if(uav) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uav->GetDesc(&uavDesc); + + if(uavDesc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER) + { + result.value.u.x = result.value.u.y = result.value.u.z = result.value.u.w = + uavDesc.Buffer.NumElements; + } + else + { + RDCWARN("Unexpected UAV dimension %d passed to bufinfo", uavDesc.ViewDimension); + + m_pDevice->AddDebugMessage( + MessageCategory::Shaders, MessageSeverity::High, MessageSource::RuntimeWarning, + StringFormat::Fmt( + "Shader debugging %d: %s\nUAV being queried by bufinfo is not a buffer", + m_instruction, opString)); + } + } + else + { + RDCWARN("UAV is NULL being queried by bufinfo"); + + m_pDevice->AddDebugMessage( + MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\nUAV being queried by bufinfo is NULL", + m_instruction, opString)); + } + + SAFE_RELEASE(uav); + } + else + { + ID3D11ShaderResourceView *srv = NULL; + switch(GetShaderType()) + { + case D3D11_ShaderType_Vertex: context->VSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Hull: context->HSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Domain: context->DSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Geometry: context->GSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Pixel: context->PSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Compute: context->CSGetShaderResources(slot, 1, &srv); break; + } + + if(srv) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srv->GetDesc(&srvDesc); + + if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER) + { + result.value.u.x = result.value.u.y = result.value.u.z = result.value.u.w = + srvDesc.Buffer.NumElements; + } + else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) + { + result.value.u.x = result.value.u.y = result.value.u.z = result.value.u.w = + srvDesc.BufferEx.NumElements; + } + else + { + RDCWARN("Unexpected SRV dimension %d passed to bufinfo", srvDesc.ViewDimension); + + m_pDevice->AddDebugMessage( + MessageCategory::Shaders, MessageSeverity::High, MessageSource::RuntimeWarning, + StringFormat::Fmt( + "Shader debugging %d: %s\nSRV being queried by bufinfo is not a buffer", + m_instruction, opString)); + } + } + else + { + RDCWARN("SRV is NULL being queried by bufinfo"); + + m_pDevice->AddDebugMessage( + MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\nSRV being queried by bufinfo is NULL", + m_instruction, opString)); + } + + SAFE_RELEASE(srv); + } + + SAFE_RELEASE(context); + return result; +} + +ShaderVariable D3D11DebugAPIWrapper::GetResourceInfo(DXBC::OperandType type, UINT slot, + uint32_t mipLevel, int &dim) +{ + ID3D11DeviceContext *context = NULL; + m_pDevice->GetImmediateContext(&context); + + ShaderVariable result("", 0.0f, 0.0f, 0.0f, 0.0f); + + if(type != DXBC::TYPE_UNORDERED_ACCESS_VIEW) + { + ID3D11ShaderResourceView *srv = NULL; + switch(GetShaderType()) + { + case D3D11_ShaderType_Vertex: context->VSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Hull: context->HSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Domain: context->DSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Geometry: context->GSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Pixel: context->PSGetShaderResources(slot, 1, &srv); break; + case D3D11_ShaderType_Compute: context->CSGetShaderResources(slot, 1, &srv); break; + } + + if(srv) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srv->GetDesc(&srvDesc); + + switch(srvDesc.ViewDimension) + { + case D3D11_SRV_DIMENSION_BUFFER: + { + dim = 1; + + result.value.u.x = srvDesc.Buffer.NumElements; + result.value.u.y = 0; + result.value.u.z = 0; + result.value.u.w = 0; + break; + } + case D3D11_SRV_DIMENSION_BUFFEREX: + { + dim = 1; + + result.value.u.x = srvDesc.BufferEx.NumElements; + result.value.u.y = 0; + result.value.u.z = 0; + result.value.u.w = 0; + break; + } + case D3D11_SRV_DIMENSION_TEXTURE1D: + case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: + { + ID3D11Texture1D *tex = NULL; + srv->GetResource((ID3D11Resource **)&tex); + + dim = 1; + + if(tex) + { + bool isarray = srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + + D3D11_TEXTURE1D_DESC desc; + tex->GetDesc(&desc); + result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); + result.value.u.y = isarray ? srvDesc.Texture1DArray.ArraySize : 0; + result.value.u.z = 0; + result.value.u.w = + isarray ? srvDesc.Texture1DArray.MipLevels : srvDesc.Texture1D.MipLevels; + + if(mipLevel >= result.value.u.w) + result.value.u.x = result.value.u.y = 0; + + SAFE_RELEASE(tex); + } + break; + } + case D3D11_SRV_DIMENSION_TEXTURE2D: + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + case D3D11_SRV_DIMENSION_TEXTURE2DMS: + case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: + { + ID3D11Texture2D *tex = NULL; + srv->GetResource((ID3D11Resource **)&tex); + + dim = 2; + + if(tex) + { + D3D11_TEXTURE2D_DESC desc; + tex->GetDesc(&desc); + result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); + result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); + + if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2D) + { + result.value.u.z = 0; + result.value.u.w = srvDesc.Texture2D.MipLevels; + } + else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY) + { + result.value.u.z = srvDesc.Texture2DArray.ArraySize; + result.value.u.w = srvDesc.Texture2DArray.MipLevels; + } + else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMS) + { + result.value.u.z = 0; + result.value.u.w = 1; + } + else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY) + { + result.value.u.z = srvDesc.Texture2DMSArray.ArraySize; + result.value.u.w = 1; + } + + if(mipLevel >= result.value.u.w) + result.value.u.x = result.value.u.y = result.value.u.z = 0; + + SAFE_RELEASE(tex); + } + break; + } + case D3D11_SRV_DIMENSION_TEXTURE3D: + { + ID3D11Texture3D *tex = NULL; + srv->GetResource((ID3D11Resource **)&tex); + + dim = 3; + + if(tex) + { + D3D11_TEXTURE3D_DESC desc; + tex->GetDesc(&desc); + result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); + result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); + result.value.u.z = RDCMAX(1U, desc.Depth >> mipLevel); + result.value.u.w = srvDesc.Texture3D.MipLevels; + + if(mipLevel >= result.value.u.w) + result.value.u.x = result.value.u.y = result.value.u.z = 0; + + SAFE_RELEASE(tex); + } + break; + } + case D3D11_SRV_DIMENSION_TEXTURECUBE: + case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY: + { + ID3D11Texture2D *tex = NULL; + srv->GetResource((ID3D11Resource **)&tex); + + dim = 2; + + if(tex) + { + bool isarray = srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY; + + D3D11_TEXTURE2D_DESC desc; + tex->GetDesc(&desc); + result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); + result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); + + // the spec says "If srcResource is a TextureCubeArray, [...]. dest.z is set to an + // undefined value." + // but that's stupid, and implementations seem to return the number of cubes + result.value.u.z = isarray ? srvDesc.TextureCubeArray.NumCubes : 0; + result.value.u.w = + isarray ? srvDesc.TextureCubeArray.MipLevels : srvDesc.TextureCube.MipLevels; + + if(mipLevel >= result.value.u.w) + result.value.u.x = result.value.u.y = result.value.u.z = 0; + + SAFE_RELEASE(tex); + } + break; + } + } + + SAFE_RELEASE(srv); + } + } + else + { + ID3D11UnorderedAccessView *uav = NULL; + if(GetShaderType() == D3D11_ShaderType_Compute) + { + context->CSGetUnorderedAccessViews(slot, 1, &uav); + } + else + { + ID3D11RenderTargetView *rtvs[8] = {0}; + ID3D11DepthStencilView *dsv = NULL; + context->OMGetRenderTargetsAndUnorderedAccessViews(0, rtvs, &dsv, slot, 1, &uav); + + for(int i = 0; i < 8; i++) + SAFE_RELEASE(rtvs[i]); + SAFE_RELEASE(dsv); + } + + if(uav) + { + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; + uav->GetDesc(&uavDesc); + + switch(uavDesc.ViewDimension) + { + case D3D11_UAV_DIMENSION_BUFFER: + { + ID3D11Buffer *buf = NULL; + uav->GetResource((ID3D11Resource **)&buf); + + dim = 1; + + if(buf) + { + D3D11_BUFFER_DESC desc; + buf->GetDesc(&desc); + result.value.u.x = desc.ByteWidth; + result.value.u.y = 0; + result.value.u.z = 0; + result.value.u.w = 0; + + SAFE_RELEASE(buf); + } + break; + } + case D3D11_UAV_DIMENSION_TEXTURE1D: + case D3D11_UAV_DIMENSION_TEXTURE1DARRAY: + { + ID3D11Texture1D *tex = NULL; + uav->GetResource((ID3D11Resource **)&tex); + + dim = 1; + + if(tex) + { + bool isarray = uavDesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY; + + D3D11_TEXTURE1D_DESC desc; + tex->GetDesc(&desc); + result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); + result.value.u.y = isarray ? uavDesc.Texture1DArray.ArraySize : 0; + result.value.u.z = 0; + + // spec says "For UAVs (u#), the number of mip levels is always 1." + result.value.u.w = 1; + + if(mipLevel >= result.value.u.w) + result.value.u.x = result.value.u.y = 0; + + SAFE_RELEASE(tex); + } + break; + } + case D3D11_UAV_DIMENSION_TEXTURE2D: + case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: + { + ID3D11Texture2D *tex = NULL; + uav->GetResource((ID3D11Resource **)&tex); + + dim = 2; + + if(tex) + { + D3D11_TEXTURE2D_DESC desc; + tex->GetDesc(&desc); + result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); + result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); + + if(uavDesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D) + result.value.u.z = 0; + else if(uavDesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY) + result.value.u.z = uavDesc.Texture2DArray.ArraySize; + + // spec says "For UAVs (u#), the number of mip levels is always 1." + result.value.u.w = 1; + + if(mipLevel >= result.value.u.w) + result.value.u.x = result.value.u.y = result.value.u.z = 0; + + SAFE_RELEASE(tex); + } + break; + } + case D3D11_UAV_DIMENSION_TEXTURE3D: + { + ID3D11Texture3D *tex = NULL; + uav->GetResource((ID3D11Resource **)&tex); + + dim = 3; + + if(tex) + { + D3D11_TEXTURE3D_DESC desc; + tex->GetDesc(&desc); + result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); + result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); + result.value.u.z = RDCMAX(1U, desc.Depth >> mipLevel); + + // spec says "For UAVs (u#), the number of mip levels is always 1." + result.value.u.w = 1; + + if(mipLevel >= result.value.u.w) + result.value.u.x = result.value.u.y = result.value.u.z = 0; + + SAFE_RELEASE(tex); + } + break; + } + } + + SAFE_RELEASE(uav); + } + } + + SAFE_RELEASE(context); + return result; +} + +bool D3D11DebugAPIWrapper::CalculateSampleGather( + DXBC::OpcodeType opcode, ShaderDebug::SampleGatherResourceData resourceData, + ShaderDebug::SampleGatherSamplerData samplerData, ShaderVariable uv, ShaderVariable ddxCalc, + ShaderVariable ddyCalc, const int texelOffsets[3], int multisampleIndex, + float lodOrCompareValue, const uint8_t swizzle[4], ShaderDebug::GatherChannel gatherChannel, + const char *opString, ShaderVariable &output) +{ + using namespace DXBC; + + std::string funcRet = ""; + DXGI_FORMAT retFmt = DXGI_FORMAT_UNKNOWN; + + if(opcode == OPCODE_SAMPLE_C || opcode == OPCODE_SAMPLE_C_LZ || opcode == OPCODE_GATHER4_C || + opcode == OPCODE_GATHER4_PO_C || opcode == OPCODE_LOD) + { + retFmt = DXGI_FORMAT_R32G32B32A32_FLOAT; + funcRet = "float4"; + } + + std::string samplerDecl = ""; + if(samplerData.mode == SAMPLER_MODE_DEFAULT) + samplerDecl = "SamplerState s"; + else if(samplerData.mode == SAMPLER_MODE_COMPARISON) + samplerDecl = "SamplerComparisonState s"; + + std::string textureDecl = ""; + int texdim = 2; + int offsetDim = 2; + bool useOffsets = true; + if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE1D) + { + textureDecl = "Texture1D"; + texdim = 1; + offsetDim = 1; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE2D) + { + textureDecl = "Texture2D"; + texdim = 2; + offsetDim = 2; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE2DMS) + { + textureDecl = "Texture2DMS"; + texdim = 2; + offsetDim = 2; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE3D) + { + textureDecl = "Texture3D"; + texdim = 3; + offsetDim = 3; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURECUBE) + { + textureDecl = "TextureCube"; + texdim = 3; + offsetDim = 3; + useOffsets = false; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE1DARRAY) + { + textureDecl = "Texture1DArray"; + texdim = 2; + offsetDim = 1; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE2DARRAY) + { + textureDecl = "Texture2DArray"; + texdim = 3; + offsetDim = 2; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY) + { + textureDecl = "Texture2DMSArray"; + texdim = 3; + offsetDim = 2; + } + else if(resourceData.dim == RESOURCE_DIMENSION_TEXTURECUBEARRAY) + { + textureDecl = "TextureCubeArray"; + texdim = 4; + offsetDim = 3; + useOffsets = false; + } + else + { + RDCERR("Unsupported resource type %d in sample operation", resourceData.dim); + } + + { + char *typeStr[NUM_RETURN_TYPES] = { + "", // enum starts at ==1 + "unorm float", + "snorm float", + "int", + "uint", + "float", + "__", // RETURN_TYPE_MIXED + "double", + "__", // RETURN_TYPE_CONTINUED + "__", // RETURN_TYPE_UNUSED + }; + + // obviously these may be overly optimistic in some cases + // but since we don't know at debug time what the source texture format is + // we just use the fattest one necessary. There's no harm in retrieving at + // higher precision + DXGI_FORMAT fmts[NUM_RETURN_TYPES] = { + DXGI_FORMAT_UNKNOWN, // enum starts at ==1 + DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_FLOAT, + DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_MIXED + + // should maybe be double, but there is no double texture format anyway! + // spec is unclear but I presume reads are done at most at float + // precision anyway since that's the source, and converted to doubles. + DXGI_FORMAT_R32G32B32A32_FLOAT, + + DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_CONTINUED + DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_UNUSED + }; + + char buf[64] = {0}; + StringFormat::snprintf(buf, 63, "%s4", typeStr[resourceData.retType]); + + if(retFmt == DXGI_FORMAT_UNKNOWN) + { + funcRet = buf; + retFmt = fmts[resourceData.retType]; + } + + if(resourceData.dim == RESOURCE_DIMENSION_TEXTURE2DMS || + resourceData.dim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY) + { + if(resourceData.sampleCount > 0) + StringFormat::snprintf(buf, 63, "%s4, %d", typeStr[resourceData.retType], + resourceData.sampleCount); + } + + textureDecl += "<"; + textureDecl += buf; + textureDecl += "> t"; + } + + char *formats[4][2] = { + {"float(%.10f)", "int(%d)"}, + {"float2(%.10f, %.10f)", "int2(%d, %d)"}, + {"float3(%.10f, %.10f, %.10f)", "int3(%d, %d, %d)"}, + {"float4(%.10f, %.10f, %.10f, %.10f)", "int4(%d, %d, %d, %d)"}, + }; + + int texcoordType = 0; + int ddxType = 0; + int ddyType = 0; + int texdimOffs = 0; + + if(opcode == OPCODE_SAMPLE || opcode == OPCODE_SAMPLE_L || opcode == OPCODE_SAMPLE_B || + opcode == OPCODE_SAMPLE_D || opcode == OPCODE_SAMPLE_C || opcode == OPCODE_SAMPLE_C_LZ || + opcode == OPCODE_GATHER4 || opcode == OPCODE_GATHER4_C || opcode == OPCODE_GATHER4_PO || + opcode == OPCODE_GATHER4_PO_C || opcode == OPCODE_LOD) + { + // all floats + texcoordType = ddxType = ddyType = 0; + } + else if(opcode == OPCODE_LD) + { + // int address, one larger than texdim (to account for mip/slice parameter) + texdimOffs = 1; + texcoordType = 1; + + if(texdim == 4) + { + RDCERR("Unexpectedly large texture in load operation"); + } + } + else if(opcode == OPCODE_LD_MS) + { + texcoordType = 1; + + if(texdim == 4) + { + RDCERR("Unexpectedly large texture in load operation"); + } + } + + for(uint32_t i = 0; i < ddxCalc.columns; i++) + { + if(ddxType == 0 && (_isnan(ddxCalc.value.fv[i]) || !_finite(ddxCalc.value.fv[i]))) + { + RDCWARN("NaN or Inf in texlookup"); + ddxCalc.value.fv[i] = 0.0f; + + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\nNaN or Inf found in " + "texture lookup ddx - using 0.0 instead", + m_instruction, opString)); + } + if(ddyType == 0 && (_isnan(ddyCalc.value.fv[i]) || !_finite(ddyCalc.value.fv[i]))) + { + RDCWARN("NaN or Inf in texlookup"); + ddyCalc.value.fv[i] = 0.0f; + + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\nNaN or Inf found in " + "texture lookup ddy - using 0.0 instead", + m_instruction, opString)); + } + } + + for(uint32_t i = 0; i < uv.columns; i++) + { + if(texcoordType == 0 && (_isnan(uv.value.fv[i]) || !_finite(uv.value.fv[i]))) + { + RDCWARN("NaN or Inf in texlookup"); + uv.value.fv[i] = 0.0f; + + m_pDevice->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, + MessageSource::RuntimeWarning, + StringFormat::Fmt("Shader debugging %d: %s\nNaN or Inf found in " + "texture lookup uv - using 0.0 instead", + m_instruction, opString)); + } + } + + char buf[256] = {0}; + char buf2[256] = {0}; + char buf3[256] = {0}; + + // because of unions in .value we can pass the float versions and printf will interpret it as + // the right type according to formats + if(texcoordType == 0) + StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, + uv.value.f.y, uv.value.f.z, uv.value.f.w); + else + StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.i.x, + uv.value.i.y, uv.value.i.z, uv.value.i.w); + + if(ddxType == 0) + StringFormat::snprintf(buf2, 255, formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.f.x, + ddxCalc.value.f.y, ddxCalc.value.f.z, ddxCalc.value.f.w); + else + StringFormat::snprintf(buf2, 255, formats[offsetDim + texdimOffs - 1][ddxType], ddxCalc.value.i.x, + ddxCalc.value.i.y, ddxCalc.value.i.z, ddxCalc.value.i.w); + + if(ddyType == 0) + StringFormat::snprintf(buf3, 255, formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.f.x, + ddyCalc.value.f.y, ddyCalc.value.f.z, ddyCalc.value.f.w); + else + StringFormat::snprintf(buf3, 255, formats[offsetDim + texdimOffs - 1][ddyType], ddyCalc.value.i.x, + ddyCalc.value.i.y, ddyCalc.value.i.z, ddyCalc.value.i.w); + + std::string texcoords = buf; + std::string ddx = buf2; + std::string ddy = buf3; + + if(opcode == OPCODE_LD_MS) + { + StringFormat::snprintf(buf, 255, formats[0][1], multisampleIndex); + } + + std::string sampleIdx = buf; + + std::string offsets = ""; + + if(useOffsets) + { + if(offsetDim == 1) + StringFormat::snprintf(buf, 255, ", int(%d)", texelOffsets[0]); + if(offsetDim == 2) + StringFormat::snprintf(buf, 255, ", int2(%d, %d)", texelOffsets[0], texelOffsets[1]); + if(offsetDim == 3) + StringFormat::snprintf(buf, 255, ", int3(%d, %d, %d)", texelOffsets[0], texelOffsets[1], + texelOffsets[2]); + // texdim == 4 is cube arrays, no offset supported + + offsets = buf; + } + + char elems[] = "xyzw"; + std::string strSwizzle = "."; + for(int i = 0; i < 4; ++i) + { + strSwizzle += elems[swizzle[i]]; + } + + std::string strGatherChannel; + switch(gatherChannel) + { + case ShaderDebug::GatherChannel::Red: strGatherChannel = "Red"; break; + case ShaderDebug::GatherChannel::Green: strGatherChannel = "Green"; break; + case ShaderDebug::GatherChannel::Blue: strGatherChannel = "Blue"; break; + case ShaderDebug::GatherChannel::Alpha: strGatherChannel = "Alpha"; break; + } + + std::string vsProgram = "float4 main(uint id : SV_VertexID) : SV_Position {\n"; + vsProgram += "return float4((id == 2) ? 3.0f : -1.0f, (id == 0) ? -3.0f : 1.0f, 0.5, 1.0);\n"; + vsProgram += "}"; + + std::string sampleProgram; + + if(opcode == OPCODE_SAMPLE || opcode == OPCODE_SAMPLE_B || opcode == OPCODE_SAMPLE_D) + { + sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram += + "t.SampleGrad(s, " + texcoords + ", " + ddx + ", " + ddy + offsets + ")" + strSwizzle + ";"; + sampleProgram += "\n}\n"; + } + else if(opcode == OPCODE_SAMPLE_L) + { + // lod selection + StringFormat::snprintf(buf, 255, "%.10f", lodOrCompareValue); + + sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram += "t.SampleLevel(s, " + texcoords + ", " + buf + offsets + ")" + strSwizzle + ";"; + sampleProgram += "\n}\n"; + } + else if(opcode == OPCODE_SAMPLE_C || opcode == OPCODE_LOD) + { + // these operations need derivatives but have no hlsl function to call to provide them, so + // we fake it in the vertex shader + + std::string uvDim = "1"; + uvDim[0] += char(texdim + texdimOffs - 1); + + vsProgram = "void main(uint id : SV_VertexID, out float4 pos : SV_Position, out float" + uvDim + + " uv : uvs) {\n"; + + StringFormat::snprintf( + buf, 255, formats[texdim + texdimOffs - 1][texcoordType], + uv.value.f.x + ddyCalc.value.f.x * 2.0f, uv.value.f.y + ddyCalc.value.f.y * 2.0f, + uv.value.f.z + ddyCalc.value.f.z * 2.0f, uv.value.f.w + ddyCalc.value.f.w * 2.0f); + + vsProgram += "if(id == 0) uv = " + std::string(buf) + ";\n"; + + StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], uv.value.f.x, + uv.value.f.y, uv.value.f.z, uv.value.f.w); + + vsProgram += "if(id == 1) uv = " + std::string(buf) + ";\n"; + + StringFormat::snprintf( + buf, 255, formats[texdim + texdimOffs - 1][texcoordType], + uv.value.f.x + ddxCalc.value.f.x * 2.0f, uv.value.f.y + ddxCalc.value.f.y * 2.0f, + uv.value.f.z + ddxCalc.value.f.z * 2.0f, uv.value.f.w + ddxCalc.value.f.w * 2.0f); + + vsProgram += "if(id == 2) uv = " + std::string(buf) + ";\n"; + + vsProgram += "pos = float4((id == 2) ? 3.0f : -1.0f, (id == 0) ? -3.0f : 1.0f, 0.5, 1.0);\n"; + vsProgram += "}"; + + if(opcode == OPCODE_SAMPLE_C) + { + // comparison value + StringFormat::snprintf(buf, 255, "%.10f", lodOrCompareValue); + + sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; + sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + + " uv : uvs) : SV_Target0\n{\n"; + sampleProgram += + "return t.SampleCmpLevelZero(s, uv, " + std::string(buf) + offsets + ").xxxx;"; + sampleProgram += "\n}\n"; + } + else if(opcode == OPCODE_LOD) + { + sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; + sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + + " uv : uvs) : SV_Target0\n{\n"; + sampleProgram += + "return float4(t.CalculateLevelOfDetail(s, uv), t.CalculateLevelOfDetailUnclamped(s, " + "uv), 0.0f, 0.0f);"; + sampleProgram += "\n}\n"; + } + } + else if(opcode == OPCODE_SAMPLE_C_LZ) + { + // comparison value + StringFormat::snprintf(buf, 255, "%.10f", lodOrCompareValue); + + sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram += + "t.SampleCmpLevelZero(s, " + texcoords + ", " + buf + offsets + ")" + strSwizzle + ";"; + sampleProgram += "\n}\n"; + } + else if(opcode == OPCODE_LD) + { + sampleProgram = textureDecl + " : register(t0);\n\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram += "t.Load(" + texcoords + offsets + ")" + strSwizzle + ";"; + sampleProgram += "\n}\n"; + } + else if(opcode == OPCODE_LD_MS) + { + sampleProgram = textureDecl + " : register(t0);\n\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram += "t.Load(" + texcoords + ", " + sampleIdx + offsets + ")" + strSwizzle + ";"; + sampleProgram += "\n}\n"; + } + else if(opcode == OPCODE_GATHER4 || opcode == OPCODE_GATHER4_PO) + { + sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram += + "t.Gather" + strGatherChannel + "(s, " + texcoords + offsets + ")" + strSwizzle + ";"; + sampleProgram += "\n}\n"; + } + else if(opcode == OPCODE_GATHER4_C || opcode == OPCODE_GATHER4_PO_C) + { + // comparison value + StringFormat::snprintf(buf, 255, ", %.10f", lodOrCompareValue); + + sampleProgram = textureDecl + " : register(t0);\n" + samplerDecl + " : register(s0);\n\n"; + sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; + sampleProgram += "t.GatherCmp" + strGatherChannel + "(s, " + texcoords + buf + offsets + ")" + + strSwizzle + ";"; + sampleProgram += "\n}\n"; + } + + ID3D11VertexShader *vs = + m_pDevice->GetShaderCache()->MakeVShader(vsProgram.c_str(), "main", "vs_5_0"); + ID3D11PixelShader *ps = + m_pDevice->GetShaderCache()->MakePShader(sampleProgram.c_str(), "main", "ps_5_0"); + + ID3D11DeviceContext *context = NULL; + + m_pDevice->GetImmediateContext(&context); + + // back up SRV/sampler on PS slot 0 + + ID3D11ShaderResourceView *prevSRV = NULL; + ID3D11SamplerState *prevSamp = NULL; + + context->PSGetShaderResources(0, 1, &prevSRV); + context->PSGetSamplers(0, 1, &prevSamp); + + ID3D11ShaderResourceView *usedSRV = NULL; + ID3D11SamplerState *usedSamp = NULL; + + // fetch SRV and sampler from the shader stage we're debugging that this opcode wants to load from + switch(GetShaderType()) + { + case D3D11_ShaderType_Vertex: + context->VSGetShaderResources(resourceData.slot, 1, &usedSRV); + context->VSGetSamplers(samplerData.slot, 1, &usedSamp); + break; + case D3D11_ShaderType_Hull: + context->HSGetShaderResources(resourceData.slot, 1, &usedSRV); + context->HSGetSamplers(samplerData.slot, 1, &usedSamp); + break; + case D3D11_ShaderType_Domain: + context->DSGetShaderResources(resourceData.slot, 1, &usedSRV); + context->DSGetSamplers(samplerData.slot, 1, &usedSamp); + break; + case D3D11_ShaderType_Geometry: + context->GSGetShaderResources(resourceData.slot, 1, &usedSRV); + context->GSGetSamplers(samplerData.slot, 1, &usedSamp); + break; + case D3D11_ShaderType_Pixel: + context->PSGetShaderResources(resourceData.slot, 1, &usedSRV); + context->PSGetSamplers(samplerData.slot, 1, &usedSamp); + break; + case D3D11_ShaderType_Compute: + context->CSGetShaderResources(resourceData.slot, 1, &usedSRV); + context->CSGetSamplers(samplerData.slot, 1, &usedSamp); + break; + } + + // set onto PS while we perform the sample + context->PSSetShaderResources(0, 1, &usedSRV); + if(opcode == OPCODE_SAMPLE_B && samplerData.bias != 0.0f) + { + RDCASSERT(usedSamp); + + D3D11_SAMPLER_DESC desc; + usedSamp->GetDesc(&desc); + + desc.MipLODBias = RDCCLAMP(desc.MipLODBias + samplerData.bias, -15.99f, 15.99f); + + ID3D11SamplerState *replacementSamp = NULL; + HRESULT hr = m_pDevice->CreateSamplerState(&desc, &replacementSamp); + if(FAILED(hr)) + { + RDCERR("Failed to create new sampler state in debugging HRESULT: %s", ToStr(hr).c_str()); + } + else + { + context->PSSetSamplers(0, 1, &replacementSamp); + SAFE_RELEASE(replacementSamp); + } + } + else + { + context->PSSetSamplers(0, 1, &usedSamp); + } + + context->IASetInputLayout(NULL); + context->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + + context->VSSetShader(vs, NULL, 0); + context->PSSetShader(ps, NULL, 0); + + D3D11_VIEWPORT view = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; + context->RSSetViewports(1, &view); + + context->GSSetShader(NULL, NULL, 0); + context->DSSetShader(NULL, NULL, 0); + context->HSSetShader(NULL, NULL, 0); + context->CSSetShader(NULL, NULL, 0); + + context->SOSetTargets(0, NULL, NULL); + + context->RSSetState(NULL); + context->OMSetBlendState(NULL, NULL, (UINT)~0); + context->OMSetDepthStencilState(NULL, 0); + + ID3D11RenderTargetView *rtv = NULL; + + ID3D11Texture2D *rtTex = NULL; + ID3D11Texture2D *copyTex = NULL; + + D3D11_TEXTURE2D_DESC tdesc; + + RDCASSERT(retFmt != DXGI_FORMAT_UNKNOWN); + + tdesc.ArraySize = 1; + tdesc.BindFlags = D3D11_BIND_RENDER_TARGET; + tdesc.CPUAccessFlags = 0; + tdesc.Format = retFmt; + tdesc.Width = 1; + tdesc.Height = 1; + tdesc.MipLevels = 0; + tdesc.MiscFlags = 0; + tdesc.SampleDesc.Count = 1; + tdesc.SampleDesc.Quality = 0; + tdesc.Usage = D3D11_USAGE_DEFAULT; + + HRESULT hr = S_OK; + + hr = m_pDevice->CreateTexture2D(&tdesc, NULL, &rtTex); + + if(FAILED(hr)) + { + RDCERR("Failed to create RT tex HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + tdesc.BindFlags = 0; + tdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + tdesc.Usage = D3D11_USAGE_STAGING; + + hr = m_pDevice->CreateTexture2D(&tdesc, NULL, ©Tex); + + if(FAILED(hr)) + { + RDCERR("Failed to create copy tex HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + D3D11_RENDER_TARGET_VIEW_DESC rtDesc; + + rtDesc.Format = retFmt; + rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtDesc.Texture2D.MipSlice = 0; + + hr = m_pDevice->CreateRenderTargetView(rtTex, &rtDesc, &rtv); + + if(FAILED(hr)) + { + RDCERR("Failed to create rt rtv HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + context->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv, NULL, 0, 0, NULL, NULL); + context->Draw(3, 0); + + context->CopyResource(copyTex, rtTex); + + D3D11_MAPPED_SUBRESOURCE mapped; + hr = context->Map(copyTex, 0, D3D11_MAP_READ, 0, &mapped); + + if(FAILED(hr)) + { + RDCERR("Failed to map results HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + ShaderVariable lookupResult("tex", 0.0f, 0.0f, 0.0f, 0.0f); + + memcpy(lookupResult.value.iv, mapped.pData, sizeof(uint32_t) * 4); + + context->Unmap(copyTex, 0); + + SAFE_RELEASE(rtTex); + SAFE_RELEASE(copyTex); + SAFE_RELEASE(rtv); + SAFE_RELEASE(vs); + SAFE_RELEASE(ps); + + // restore whatever was on PS slot 0 before we messed with it + + context->PSSetShaderResources(0, 1, &prevSRV); + context->PSSetSamplers(0, 1, &prevSamp); + + SAFE_RELEASE(context); + + SAFE_RELEASE(prevSRV); + SAFE_RELEASE(prevSamp); + + SAFE_RELEASE(usedSRV); + SAFE_RELEASE(usedSamp); + + output = lookupResult; + return true; +} + +bool D3D11DebugAPIWrapper::CalculateMathIntrinsic(DXBC::OpcodeType opcode, + const ShaderVariable &input, + ShaderVariable &output1, ShaderVariable &output2) +{ + std::string csProgram = + "RWBuffer outval : register(u0);\n" + "cbuffer srcOper : register(b0) { float4 inval; };\n" + "[numthreads(1, 1, 1)]\n" + "void main() {\n"; + + switch(opcode) + { + case DXBC::OPCODE_RCP: csProgram += "outval[0] = rcp(inval);\n"; break; + case DXBC::OPCODE_RSQ: csProgram += "outval[0] = rsqrt(inval);\n"; break; + case DXBC::OPCODE_EXP: csProgram += "outval[0] = exp2(inval);\n"; break; + case DXBC::OPCODE_LOG: csProgram += "outval[0] = log2(inval);\n"; break; + case DXBC::OPCODE_SINCOS: csProgram += "sincos(inval, outval[0], outval[1]);\n"; break; + default: RDCERR("Unexpected opcode %d passed to CalculateMathIntrinsic", opcode); return false; + } + + csProgram += "}\n"; + + ID3D11ComputeShader *cs = + m_pDevice->GetShaderCache()->MakeCShader(csProgram.c_str(), "main", "cs_5_0"); + + ID3D11DeviceContext *context = NULL; + m_pDevice->GetImmediateContext(&context); + + // back up CB/UAV on CS slot 0 + + ID3D11Buffer *prevCB = NULL; + ID3D11UnorderedAccessView *prevUAV = NULL; + + context->CSGetConstantBuffers(0, 1, &prevCB); + context->CSGetUnorderedAccessViews(0, 1, &prevUAV); + + ID3D11Buffer *constBuf = NULL; + + D3D11_BUFFER_DESC cdesc; + + cdesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cdesc.CPUAccessFlags = 0; + cdesc.MiscFlags = 0; + cdesc.StructureByteStride = sizeof(Vec4f); + cdesc.ByteWidth = sizeof(Vec4f); + cdesc.Usage = D3D11_USAGE_DEFAULT; + + D3D11_SUBRESOURCE_DATA operData = {}; + operData.pSysMem = &input.value.uv[0]; + operData.SysMemPitch = sizeof(Vec4f); + operData.SysMemSlicePitch = sizeof(Vec4f); + + HRESULT hr = m_pDevice->CreateBuffer(&cdesc, &operData, &constBuf); + if(FAILED(hr)) + { + RDCERR("Failed to create constant buf HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + context->CSSetConstantBuffers(0, 1, &constBuf); + + context->CSSetShader(cs, NULL, 0); + + ID3D11UnorderedAccessView *uav = NULL; + + ID3D11Buffer *uavBuf = NULL; + ID3D11Buffer *copyBuf = NULL; + + D3D11_BUFFER_DESC bdesc; + + bdesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; + bdesc.CPUAccessFlags = 0; + bdesc.MiscFlags = 0; + bdesc.StructureByteStride = sizeof(Vec4f); + bdesc.ByteWidth = sizeof(Vec4f) * 2; + bdesc.Usage = D3D11_USAGE_DEFAULT; + + hr = m_pDevice->CreateBuffer(&bdesc, NULL, &uavBuf); + + if(FAILED(hr)) + { + RDCERR("Failed to create UAV buf HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + bdesc.BindFlags = 0; + bdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + bdesc.Usage = D3D11_USAGE_STAGING; + + hr = m_pDevice->CreateBuffer(&bdesc, NULL, ©Buf); + + if(FAILED(hr)) + { + RDCERR("Failed to create copy buf HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; + + uavDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; + uavDesc.Buffer.FirstElement = 0; + uavDesc.Buffer.NumElements = 2; + uavDesc.Buffer.Flags = 0; + + hr = m_pDevice->CreateUnorderedAccessView(uavBuf, &uavDesc, &uav); + + if(FAILED(hr)) + { + RDCERR("Failed to create uav HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + context->CSSetUnorderedAccessViews(0, 1, &uav, NULL); + context->Dispatch(1, 1, 1); + + context->CopyResource(copyBuf, uavBuf); + + D3D11_MAPPED_SUBRESOURCE mapped; + hr = context->Map(copyBuf, 0, D3D11_MAP_READ, 0, &mapped); + + if(FAILED(hr)) + { + RDCERR("Failed to map results HRESULT: %s", ToStr(hr).c_str()); + return false; + } + + uint32_t *resA = (uint32_t *)mapped.pData; + uint32_t *resB = resA + 4; + + memcpy(output1.value.uv, resA, sizeof(uint32_t) * 4); + memcpy(output2.value.uv, resB, sizeof(uint32_t) * 4); + + context->Unmap(copyBuf, 0); + + SAFE_RELEASE(constBuf); + SAFE_RELEASE(uavBuf); + SAFE_RELEASE(copyBuf); + SAFE_RELEASE(uav); + SAFE_RELEASE(cs); + + // restore whatever was on CS slot 0 before we messed with it + + UINT append[] = {~0U}; + context->CSSetConstantBuffers(0, 1, &prevCB); + context->CSSetUnorderedAccessViews(0, 1, &prevUAV, append); + + SAFE_RELEASE(context); + + SAFE_RELEASE(prevCB); + SAFE_RELEASE(prevUAV); + + return true; +} + ShaderDebug::State D3D11DebugManager::CreateShaderDebugState(ShaderDebugTrace &trace, int quadIdx, DXBC::DXBCFile *dxbc, const ShaderReflection &refl, @@ -247,7 +1610,7 @@ ShaderDebug::State D3D11DebugManager::CreateShaderDebugState(ShaderDebugTrace &t using namespace DXBC; using namespace ShaderDebug; - State initialState = State(quadIdx, &trace, dxbc, m_pDevice); + State initialState = State(quadIdx, &trace, dxbc); // use pixel shader here to get inputs @@ -1097,12 +2460,14 @@ ShaderDebugTrace D3D11Replay::DebugVertex(uint32_t eventId, uint32_t vertid, uin D3D11MarkerRegion simloop("Simulation Loop"); + D3D11DebugAPIWrapper apiWrapper(m_pDevice, dxbc, global); + for(int cycleCounter = 0;; cycleCounter++) { if(initialState.Finished()) break; - initialState = initialState.GetNext(global, NULL); + initialState = initialState.GetNext(global, &apiWrapper, NULL); if(dxbc->m_DebugInfo) { @@ -2286,6 +3651,8 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim D3D11MarkerRegion simloop("Simulation Loop"); + D3D11DebugAPIWrapper apiWrapper(m_pDevice, dxbc, global); + // simulate lockstep until all threads are finished bool finished = true; do @@ -2293,7 +3660,7 @@ void ExtractInputsPS(PSInput IN, float4 debug_pixelPos : SV_Position, uint prim for(size_t i = 0; i < 4; i++) { if(activeMask[i]) - newquad[i] = curquad[i].GetNext(global, curquad); + newquad[i] = curquad[i].GetNext(global, &apiWrapper, curquad); else newquad[i] = curquad[i]; } @@ -2479,12 +3846,14 @@ ShaderDebugTrace D3D11Replay::DebugThread(uint32_t eventId, const uint32_t group states.push_back((State)initialState); + D3D11DebugAPIWrapper apiWrapper(m_pDevice, dxbc, global); + for(int cycleCounter = 0;; cycleCounter++) { if(initialState.Finished()) break; - initialState = initialState.GetNext(global, NULL); + initialState = initialState.GetNext(global, &apiWrapper, NULL); if(dxbc->m_DebugInfo) { diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp index 0b9d6c9a8..5f269fd65 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.cpp @@ -23,14 +23,8 @@ * THE SOFTWARE. ******************************************************************************/ -// TODO remove me #include "dxbc_debug.h" -#include #include -#include "api/replay/renderdoc_replay.h" -#include "common/common.h" -#include "driver/d3d11/d3d11_device.h" -#include "driver/d3d11/d3d11_shader_cache.h" #include "maths/formatpacking.h" #include "dxbc_inspect.h" @@ -1484,7 +1478,7 @@ static uint32_t PopCount(uint32_t x) return (((x + (x >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; } -State State::GetNext(GlobalState &global, State quad[4]) const +State State::GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State quad[4]) const { State s = *this; @@ -1495,6 +1489,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const const ASMOperation &op = s.dxbc->GetInstruction((size_t)s.nextInstruction); + apiWrapper->SetCurrentInstruction(s.nextInstruction); s.nextInstruction++; s.flags = ShaderEvents::NoEvent; @@ -2090,166 +2085,24 @@ State State::GetNext(GlobalState &global, State quad[4]) const case OPCODE_RSQ: case OPCODE_EXP: case OPCODE_LOG: - case OPCODE_SINCOS: { - std::string csProgram = - "RWBuffer outval : register(u0);\n" - "cbuffer srcOper : register(b0) { float4 inval; };\n" - "[numthreads(1, 1, 1)]\n" - "void main() {\n"; - - switch(op.operation) - { - case OPCODE_RCP: csProgram += "outval[0] = rcp(inval);\n"; break; - case OPCODE_RSQ: csProgram += "outval[0] = rsqrt(inval);\n"; break; - case OPCODE_EXP: csProgram += "outval[0] = exp2(inval);\n"; break; - case OPCODE_LOG: csProgram += "outval[0] = log2(inval);\n"; break; - case OPCODE_SINCOS: csProgram += "sincos(inval, outval[0], outval[1]);\n"; break; - } - - csProgram += "}\n"; - - ID3D11ComputeShader *cs = - device->GetShaderCache()->MakeCShader(csProgram.c_str(), "main", "cs_5_0"); - - ID3D11DeviceContext *context = NULL; - - device->GetImmediateContext(&context); - - // back up CB/UAV on CS slot 0 - - ID3D11Buffer *prevCB = NULL; - ID3D11UnorderedAccessView *prevUAV = NULL; - - context->CSGetConstantBuffers(0, 1, &prevCB); - context->CSGetUnorderedAccessViews(0, 1, &prevUAV); - - ID3D11Buffer *constBuf = NULL; - - D3D11_BUFFER_DESC cdesc; - - cdesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cdesc.CPUAccessFlags = 0; - cdesc.MiscFlags = 0; - cdesc.StructureByteStride = sizeof(Vec4f); - cdesc.ByteWidth = sizeof(Vec4f); - cdesc.Usage = D3D11_USAGE_DEFAULT; - - D3D11_SUBRESOURCE_DATA operData = {}; - operData.pSysMem = &srcOpers[0].value.uv[0]; - operData.SysMemPitch = sizeof(Vec4f); - operData.SysMemSlicePitch = sizeof(Vec4f); - - if(op.operation == OPCODE_SINCOS) - operData.pSysMem = &srcOpers[1].value.uv[0]; - - HRESULT hr = S_OK; - - hr = device->CreateBuffer(&cdesc, &operData, &constBuf); - - if(FAILED(hr)) - { - RDCERR("Failed to create constant buf HRESULT: %s", ToStr(hr).c_str()); - return s; - } - - context->CSSetConstantBuffers(0, 1, &constBuf); - - context->CSSetShader(cs, NULL, 0); - - ID3D11UnorderedAccessView *uav = NULL; - - ID3D11Buffer *uavBuf = NULL; - ID3D11Buffer *copyBuf = NULL; - - D3D11_BUFFER_DESC bdesc; - - bdesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; - bdesc.CPUAccessFlags = 0; - bdesc.MiscFlags = 0; - bdesc.StructureByteStride = sizeof(Vec4f); - bdesc.ByteWidth = sizeof(Vec4f) * 2; - bdesc.Usage = D3D11_USAGE_DEFAULT; - - hr = device->CreateBuffer(&bdesc, NULL, &uavBuf); - - if(FAILED(hr)) - { - RDCERR("Failed to create UAV buf HRESULT: %s", ToStr(hr).c_str()); - return s; - } - - bdesc.BindFlags = 0; - bdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - bdesc.Usage = D3D11_USAGE_STAGING; - - hr = device->CreateBuffer(&bdesc, NULL, ©Buf); - - if(FAILED(hr)) - { - RDCERR("Failed to create copy buf HRESULT: %s", ToStr(hr).c_str()); - return s; - } - - D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {}; - - uavDesc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; - uavDesc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER; - uavDesc.Buffer.FirstElement = 0; - uavDesc.Buffer.NumElements = 2; - uavDesc.Buffer.Flags = 0; - - hr = device->CreateUnorderedAccessView(uavBuf, &uavDesc, &uav); - - if(FAILED(hr)) - { - RDCERR("Failed to create uav HRESULT: %s", ToStr(hr).c_str()); - return s; - } - - context->CSSetUnorderedAccessViews(0, 1, &uav, NULL); - context->Dispatch(1, 1, 1); - - context->CopyResource(copyBuf, uavBuf); - - D3D11_MAPPED_SUBRESOURCE mapped; - hr = context->Map(copyBuf, 0, D3D11_MAP_READ, 0, &mapped); - - if(FAILED(hr)) - { - RDCERR("Failed to map results HRESULT: %s", ToStr(hr).c_str()); - return s; - } - ShaderVariable calcResultA("calcA", 0.0f, 0.0f, 0.0f, 0.0f); ShaderVariable calcResultB("calcB", 0.0f, 0.0f, 0.0f, 0.0f); - - uint32_t *resA = (uint32_t *)mapped.pData; - uint32_t *resB = resA + 4; - - memcpy(calcResultA.value.uv, resA, sizeof(uint32_t) * 4); - memcpy(calcResultB.value.uv, resB, sizeof(uint32_t) * 4); - - context->Unmap(copyBuf, 0); - - SAFE_RELEASE(constBuf); - SAFE_RELEASE(uavBuf); - SAFE_RELEASE(copyBuf); - SAFE_RELEASE(uav); - SAFE_RELEASE(cs); - - // restore whatever was on CS slot 0 before we messed with it - - UINT append[] = {~0U}; - context->CSSetConstantBuffers(0, 1, &prevCB); - context->CSSetUnorderedAccessViews(0, 1, &prevUAV, append); - - SAFE_RELEASE(context); - - SAFE_RELEASE(prevCB); - SAFE_RELEASE(prevUAV); - - if(op.operation == OPCODE_SINCOS) + if(apiWrapper->CalculateMathIntrinsic(op.operation, srcOpers[0], calcResultA, calcResultB)) + { + s.SetDst(op.operands[0], op, calcResultA); + } + else + { + return s; + } + break; + } + case OPCODE_SINCOS: + { + ShaderVariable calcResultA("calcA", 0.0f, 0.0f, 0.0f, 0.0f); + ShaderVariable calcResultB("calcB", 0.0f, 0.0f, 0.0f, 0.0f); + if(apiWrapper->CalculateMathIntrinsic(OPCODE_SINCOS, srcOpers[1], calcResultA, calcResultB)) { if(op.operands[0].type != TYPE_NULL) s.SetDst(op.operands[0], op, calcResultA); @@ -2258,9 +2111,8 @@ State State::GetNext(GlobalState &global, State quad[4]) const } else { - s.SetDst(op.operands[0], op, calcResultA); + return s; } - break; } @@ -2902,7 +2754,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const if(load && !srv && !gsm && (fmt.numComps != 1 || fmt.byteWidth != 4)) { - device->AddDebugMessage( + apiWrapper->AddDebugMessage( MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, StringFormat::Fmt( "Shader debugging %d: %s\n" @@ -3076,7 +2928,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const if(!global.sampleEvalCache.empty()) { - device->AddDebugMessage( + apiWrapper->AddDebugMessage( MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, StringFormat::Fmt( "Shader debugging %d: %s\n" @@ -3093,126 +2945,12 @@ State State::GetNext(GlobalState &global, State quad[4]) const case OPCODE_SAMPLE_INFO: case OPCODE_SAMPLE_POS: { - ID3D11DeviceContext *context = NULL; - device->GetImmediateContext(&context); - - ShaderVariable result("", 0U, 0U, 0U, 0U); - - ID3D11Resource *res = NULL; - - if(op.operands[1].type == TYPE_RASTERIZER) - { - ID3D11RenderTargetView *rtv[8] = {}; - ID3D11DepthStencilView *dsv = NULL; - - context->OMGetRenderTargets(8, rtv, &dsv); - - // try depth first - both should match sample count though to be valid - if(dsv) - { - dsv->GetResource(&res); - } - else - { - for(size_t i = 0; i < ARRAY_COUNT(rtv); i++) - { - if(rtv[i]) - { - rtv[i]->GetResource(&res); - break; - } - } - } - - if(!res) - { - RDCWARN("No targets bound for output when calling sampleinfo on rasterizer"); - - device->AddDebugMessage( - MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\n" - "No targets bound for output when calling sampleinfo on rasterizer", - s.nextInstruction - 1, op.str.c_str())); - } - - for(size_t i = 0; i < ARRAY_COUNT(rtv); i++) - SAFE_RELEASE(rtv[i]); - SAFE_RELEASE(dsv); - } - else if(op.operands[1].type == TYPE_RESOURCE && op.operands[1].indices.size() == 1 && - op.operands[1].indices[0].absolute && !op.operands[1].indices[0].relative) - { - UINT slot = (UINT)(op.operands[1].indices[0].index & 0xffffffff); - - ID3D11ShaderResourceView *srv = NULL; - if(s.dxbc->m_Type == D3D11_ShaderType_Vertex) - context->VSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Hull) - context->HSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Domain) - context->DSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Geometry) - context->GSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Pixel) - context->PSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Compute) - context->CSGetShaderResources(slot, 1, &srv); - - if(srv) - { - srv->GetResource(&res); - } - else - { - RDCWARN("SRV is NULL being queried by sampleinfo"); - - device->AddDebugMessage( - MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\nSRV is NULL being queried by sampleinfo", - s.nextInstruction - 1, op.str.c_str())); - } - - SAFE_RELEASE(srv); - } - else - { - RDCWARN("unexpected operand type to sample_info"); - } - - if(res) - { - D3D11_RESOURCE_DIMENSION dim = D3D11_RESOURCE_DIMENSION_UNKNOWN; - res->GetType(&dim); - - if(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D) - { - D3D11_TEXTURE2D_DESC desc; - ((ID3D11Texture2D *)res)->GetDesc(&desc); - - // returns 1 for non-multisampled resources - result.value.u.x = RDCMAX(1U, desc.SampleDesc.Count); - } - else - { - if(op.operands[1].type == TYPE_RASTERIZER) - { - // special behaviour for non-2D (i.e. by definition non-multisampled) textures when - // querying the rasterizer, just return 1. - result.value.u.x = 1; - } - else - { - device->AddDebugMessage( - MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\nResource specified is not a 2D texture", - s.nextInstruction - 1, op.str.c_str())); - - result.value.u.x = 0; - } - } - - SAFE_RELEASE(res); - } + bool isAbsoluteResource = + (op.operands[1].indices.size() == 1 && op.operands[1].indices[0].absolute && + !op.operands[1].indices[0].relative); + UINT slot = (UINT)(op.operands[1].indices[0].index & 0xffffffff); + ShaderVariable result = + apiWrapper->GetSampleInfo(op.operands[1].type, isAbsoluteResource, slot, op.str.c_str()); // "If there is no resource bound to the specified slot, 0 is returned." @@ -3242,7 +2980,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const { RDCWARN("Non-multisampled texture being passed to sample_pos"); - device->AddDebugMessage( + apiWrapper->AddDebugMessage( MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, StringFormat::Fmt( "Shader debugging %d: %s\nNon-multisampled texture being passed to sample_pos", @@ -3352,118 +3090,16 @@ State State::GetNext(GlobalState &global, State quad[4]) const s.SetDst(op.operands[0], op, result); - SAFE_RELEASE(context); - break; } case OPCODE_BUFINFO: { - ID3D11DeviceContext *context = NULL; - device->GetImmediateContext(&context); - if(op.operands[1].indices.size() == 1 && op.operands[1].indices[0].absolute && !op.operands[1].indices[0].relative) { UINT slot = (UINT)(op.operands[1].indices[0].index & 0xffffffff); - - ShaderVariable result("", 0U, 0U, 0U, 0U); - - if(op.operands[1].type == TYPE_UNORDERED_ACCESS_VIEW) - { - ID3D11UnorderedAccessView *uav = NULL; - if(s.dxbc->m_Type == D3D11_ShaderType_Compute) - context->CSGetUnorderedAccessViews(slot, 1, &uav); - else - context->OMGetRenderTargetsAndUnorderedAccessViews(0, NULL, NULL, slot, 1, &uav); - - if(uav) - { - D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; - uav->GetDesc(&uavDesc); - - if(uavDesc.ViewDimension == D3D11_UAV_DIMENSION_BUFFER) - { - result.value.u.x = result.value.u.y = result.value.u.z = result.value.u.w = - uavDesc.Buffer.NumElements; - } - else - { - RDCWARN("Unexpected UAV dimension %d passed to bufinfo", uavDesc.ViewDimension); - - device->AddDebugMessage( - MessageCategory::Shaders, MessageSeverity::High, MessageSource::RuntimeWarning, - StringFormat::Fmt( - "Shader debugging %d: %s\nUAV being queried by bufinfo is not a buffer", - s.nextInstruction - 1, op.str.c_str())); - } - } - else - { - RDCWARN("UAV is NULL being queried by bufinfo"); - - device->AddDebugMessage( - MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\nUAV being queried by bufinfo is NULL", - s.nextInstruction - 1, op.str.c_str())); - } - - SAFE_RELEASE(uav); - } - else - { - ID3D11ShaderResourceView *srv = NULL; - if(s.dxbc->m_Type == D3D11_ShaderType_Vertex) - context->VSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Hull) - context->HSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Domain) - context->DSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Geometry) - context->GSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Pixel) - context->PSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Compute) - context->CSGetShaderResources(slot, 1, &srv); - - if(srv) - { - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srv->GetDesc(&srvDesc); - - if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_BUFFER) - { - result.value.u.x = result.value.u.y = result.value.u.z = result.value.u.w = - srvDesc.Buffer.NumElements; - } - else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_BUFFEREX) - { - result.value.u.x = result.value.u.y = result.value.u.z = result.value.u.w = - srvDesc.BufferEx.NumElements; - } - else - { - RDCWARN("Unexpected SRV dimension %d passed to bufinfo", srvDesc.ViewDimension); - - device->AddDebugMessage( - MessageCategory::Shaders, MessageSeverity::High, MessageSource::RuntimeWarning, - StringFormat::Fmt( - "Shader debugging %d: %s\nSRV being queried by bufinfo is not a buffer", - s.nextInstruction - 1, op.str.c_str())); - } - } - else - { - RDCWARN("SRV is NULL being queried by bufinfo"); - - device->AddDebugMessage( - MessageCategory::Shaders, MessageSeverity::Medium, MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\nSRV being queried by bufinfo is NULL", - s.nextInstruction - 1, op.str.c_str())); - } - - SAFE_RELEASE(srv); - } + ShaderVariable result = apiWrapper->GetBufferInfo(op.operands[1].type, slot, op.str.c_str()); // apply swizzle ShaderVariable swizzled("", 0.0f, 0.0f, 0.0f, 0.0f); @@ -3494,8 +3130,6 @@ State State::GetNext(GlobalState &global, State quad[4]) const s.SetDst(op.operands[0], op, ShaderVariable("", 0.0f, 0.0f, 0.0f, 0.0f)); } - SAFE_RELEASE(context); - break; } @@ -3504,325 +3138,12 @@ State State::GetNext(GlobalState &global, State quad[4]) const // spec says "srcMipLevel is read as an unsigned integer scalar" uint32_t mipLevel = srcOpers[0].value.u.x; - ID3D11DeviceContext *context = NULL; - device->GetImmediateContext(&context); - if(op.operands[2].indices.size() == 1 && op.operands[2].indices[0].absolute && !op.operands[2].indices[0].relative) { - UINT slot = (UINT)(op.operands[2].indices[0].index & 0xffffffff); - - ShaderVariable result("", 0.0f, 0.0f, 0.0f, 0.0f); - int dim = 0; - - if(op.operands[2].type != TYPE_UNORDERED_ACCESS_VIEW) - { - ID3D11ShaderResourceView *srv = NULL; - if(s.dxbc->m_Type == D3D11_ShaderType_Vertex) - context->VSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Hull) - context->HSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Domain) - context->DSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Geometry) - context->GSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Pixel) - context->PSGetShaderResources(slot, 1, &srv); - else if(s.dxbc->m_Type == D3D11_ShaderType_Compute) - context->CSGetShaderResources(slot, 1, &srv); - - if(srv) - { - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srv->GetDesc(&srvDesc); - - switch(srvDesc.ViewDimension) - { - case D3D11_SRV_DIMENSION_BUFFER: - { - dim = 1; - - result.value.u.x = srvDesc.Buffer.NumElements; - result.value.u.y = 0; - result.value.u.z = 0; - result.value.u.w = 0; - break; - } - case D3D11_SRV_DIMENSION_BUFFEREX: - { - dim = 1; - - result.value.u.x = srvDesc.BufferEx.NumElements; - result.value.u.y = 0; - result.value.u.z = 0; - result.value.u.w = 0; - break; - } - case D3D11_SRV_DIMENSION_TEXTURE1D: - case D3D11_SRV_DIMENSION_TEXTURE1DARRAY: - { - ID3D11Texture1D *tex = NULL; - srv->GetResource((ID3D11Resource **)&tex); - - dim = 1; - - if(tex) - { - bool isarray = srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY; - - D3D11_TEXTURE1D_DESC desc; - tex->GetDesc(&desc); - result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); - result.value.u.y = isarray ? srvDesc.Texture1DArray.ArraySize : 0; - result.value.u.z = 0; - result.value.u.w = - isarray ? srvDesc.Texture1DArray.MipLevels : srvDesc.Texture1D.MipLevels; - - if(mipLevel >= result.value.u.w) - result.value.u.x = result.value.u.y = 0; - - SAFE_RELEASE(tex); - } - break; - } - case D3D11_SRV_DIMENSION_TEXTURE2D: - case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: - case D3D11_SRV_DIMENSION_TEXTURE2DMS: - case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: - { - ID3D11Texture2D *tex = NULL; - srv->GetResource((ID3D11Resource **)&tex); - - dim = 2; - - if(tex) - { - D3D11_TEXTURE2D_DESC desc; - tex->GetDesc(&desc); - result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); - result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); - - if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2D) - { - result.value.u.z = 0; - result.value.u.w = srvDesc.Texture2D.MipLevels; - } - else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DARRAY) - { - result.value.u.z = srvDesc.Texture2DArray.ArraySize; - result.value.u.w = srvDesc.Texture2DArray.MipLevels; - } - else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMS) - { - result.value.u.z = 0; - result.value.u.w = 1; - } - else if(srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY) - { - result.value.u.z = srvDesc.Texture2DMSArray.ArraySize; - result.value.u.w = 1; - } - - if(mipLevel >= result.value.u.w) - result.value.u.x = result.value.u.y = result.value.u.z = 0; - - SAFE_RELEASE(tex); - } - break; - } - case D3D11_SRV_DIMENSION_TEXTURE3D: - { - ID3D11Texture3D *tex = NULL; - srv->GetResource((ID3D11Resource **)&tex); - - dim = 3; - - if(tex) - { - D3D11_TEXTURE3D_DESC desc; - tex->GetDesc(&desc); - result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); - result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); - result.value.u.z = RDCMAX(1U, desc.Depth >> mipLevel); - result.value.u.w = srvDesc.Texture3D.MipLevels; - - if(mipLevel >= result.value.u.w) - result.value.u.x = result.value.u.y = result.value.u.z = 0; - - SAFE_RELEASE(tex); - } - break; - } - case D3D11_SRV_DIMENSION_TEXTURECUBE: - case D3D11_SRV_DIMENSION_TEXTURECUBEARRAY: - { - ID3D11Texture2D *tex = NULL; - srv->GetResource((ID3D11Resource **)&tex); - - dim = 2; - - if(tex) - { - bool isarray = srvDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE1DARRAY; - - D3D11_TEXTURE2D_DESC desc; - tex->GetDesc(&desc); - result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); - result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); - - // the spec says "If srcResource is a TextureCubeArray, [...]. dest.z is set to an - // undefined value." - // but that's stupid, and implementations seem to return the number of cubes - result.value.u.z = isarray ? srvDesc.TextureCubeArray.NumCubes : 0; - result.value.u.w = - isarray ? srvDesc.TextureCubeArray.MipLevels : srvDesc.TextureCube.MipLevels; - - if(mipLevel >= result.value.u.w) - result.value.u.x = result.value.u.y = result.value.u.z = 0; - - SAFE_RELEASE(tex); - } - break; - } - } - - SAFE_RELEASE(srv); - } - } - else - { - ID3D11UnorderedAccessView *uav = NULL; - if(s.dxbc->m_Type == D3D11_ShaderType_Compute) - { - context->CSGetUnorderedAccessViews(slot, 1, &uav); - } - else - { - ID3D11RenderTargetView *rtvs[8] = {0}; - ID3D11DepthStencilView *dsv = NULL; - context->OMGetRenderTargetsAndUnorderedAccessViews(0, rtvs, &dsv, slot, 1, &uav); - - for(int i = 0; i < 8; i++) - SAFE_RELEASE(rtvs[i]); - SAFE_RELEASE(dsv); - } - - if(uav) - { - D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc; - uav->GetDesc(&uavDesc); - - switch(uavDesc.ViewDimension) - { - case D3D11_UAV_DIMENSION_BUFFER: - { - ID3D11Buffer *buf = NULL; - uav->GetResource((ID3D11Resource **)&buf); - - dim = 1; - - if(buf) - { - D3D11_BUFFER_DESC desc; - buf->GetDesc(&desc); - result.value.u.x = desc.ByteWidth; - result.value.u.y = 0; - result.value.u.z = 0; - result.value.u.w = 0; - - SAFE_RELEASE(buf); - } - break; - } - case D3D11_UAV_DIMENSION_TEXTURE1D: - case D3D11_UAV_DIMENSION_TEXTURE1DARRAY: - { - ID3D11Texture1D *tex = NULL; - uav->GetResource((ID3D11Resource **)&tex); - - dim = 1; - - if(tex) - { - bool isarray = uavDesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE1DARRAY; - - D3D11_TEXTURE1D_DESC desc; - tex->GetDesc(&desc); - result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); - result.value.u.y = isarray ? uavDesc.Texture1DArray.ArraySize : 0; - result.value.u.z = 0; - - // spec says "For UAVs (u#), the number of mip levels is always 1." - result.value.u.w = 1; - - if(mipLevel >= result.value.u.w) - result.value.u.x = result.value.u.y = 0; - - SAFE_RELEASE(tex); - } - break; - } - case D3D11_UAV_DIMENSION_TEXTURE2D: - case D3D11_UAV_DIMENSION_TEXTURE2DARRAY: - { - ID3D11Texture2D *tex = NULL; - uav->GetResource((ID3D11Resource **)&tex); - - dim = 2; - - if(tex) - { - D3D11_TEXTURE2D_DESC desc; - tex->GetDesc(&desc); - result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); - result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); - - if(uavDesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2D) - result.value.u.z = 0; - else if(uavDesc.ViewDimension == D3D11_UAV_DIMENSION_TEXTURE2DARRAY) - result.value.u.z = uavDesc.Texture2DArray.ArraySize; - - // spec says "For UAVs (u#), the number of mip levels is always 1." - result.value.u.w = 1; - - if(mipLevel >= result.value.u.w) - result.value.u.x = result.value.u.y = result.value.u.z = 0; - - SAFE_RELEASE(tex); - } - break; - } - case D3D11_UAV_DIMENSION_TEXTURE3D: - { - ID3D11Texture3D *tex = NULL; - uav->GetResource((ID3D11Resource **)&tex); - - dim = 3; - - if(tex) - { - D3D11_TEXTURE3D_DESC desc; - tex->GetDesc(&desc); - result.value.u.x = RDCMAX(1U, desc.Width >> mipLevel); - result.value.u.y = RDCMAX(1U, desc.Height >> mipLevel); - result.value.u.z = RDCMAX(1U, desc.Depth >> mipLevel); - - // spec says "For UAVs (u#), the number of mip levels is always 1." - result.value.u.w = 1; - - if(mipLevel >= result.value.u.w) - result.value.u.x = result.value.u.y = result.value.u.z = 0; - - SAFE_RELEASE(tex); - } - break; - } - } - - SAFE_RELEASE(uav); - } - } + UINT slot = (UINT)(op.operands[2].indices[0].index & 0xffffffff); + ShaderVariable result = apiWrapper->GetResourceInfo(op.operands[2].type, slot, mipLevel, dim); // need a valid dimension even if the resource was unbound, so // search for the declaration @@ -3830,7 +3151,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const { for(size_t i = 0; i < s.dxbc->GetNumDeclarations(); i++) { - const DXBC::ASMDecl &decl = dxbc->GetDeclaration(i); + const DXBC::ASMDecl &decl = s.dxbc->GetDeclaration(i); if(decl.declaration == OPCODE_DCL_RESOURCE && decl.operand.type == TYPE_RESOURCE && decl.operand.indices.size() == 1 && @@ -3919,8 +3240,6 @@ State State::GetNext(GlobalState &global, State quad[4]) const s.SetDst(op.operands[0], op, ShaderVariable("", 0.0f, 0.0f, 0.0f, 0.0f)); } - SAFE_RELEASE(context); - break; } case OPCODE_SAMPLE: @@ -3937,43 +3256,22 @@ State State::GetNext(GlobalState &global, State quad[4]) const case OPCODE_GATHER4_PO_C: case OPCODE_LOD: { - std::string sampler = ""; - std::string texture = ""; - std::string funcRet = ""; - DXGI_FORMAT retFmt = DXGI_FORMAT_UNKNOWN; - if(op.operation != OPCODE_LOD) - { s.flags = ShaderEvents::SampleLoadGather; - } - if(op.operation == OPCODE_SAMPLE_C || op.operation == OPCODE_SAMPLE_C_LZ || - op.operation == OPCODE_GATHER4_C || op.operation == OPCODE_GATHER4_PO_C || - op.operation == OPCODE_LOD) + SamplerMode samplerMode = NUM_SAMPLERS; + ResourceDimension resourceDim = RESOURCE_DIMENSION_UNKNOWN; + ResourceRetType resourceRetType = RETURN_TYPE_UNKNOWN; + int sampleCount = 0; + + for(size_t i = 0; i < dxbc->GetNumDeclarations(); i++) { - retFmt = DXGI_FORMAT_R32G32B32A32_FLOAT; - funcRet = "float4"; - } - - bool useOffsets = true; - int texdim = 2; - int offsdim = 2; // ddN and offset dimension - - DXBC::ResourceDimension resourceDim = DXBC::RESOURCE_DIMENSION_UNKNOWN; - - for(size_t i = 0; i < s.dxbc->GetNumDeclarations(); i++) - { - const DXBC::ASMDecl &decl = dxbc->GetDeclaration(i); + const ASMDecl &decl = dxbc->GetDeclaration(i); if(decl.declaration == OPCODE_DCL_SAMPLER && op.operands.size() > 3 && decl.operand.indices == op.operands[3].indices) { - if(decl.samplerMode == SAMPLER_MODE_DEFAULT) - sampler = "SamplerState s"; - else if(decl.samplerMode == SAMPLER_MODE_COMPARISON) - sampler = "SamplerComparisonState s"; - else - RDCERR("Unsupported sampler type %d in sample operation", decl.samplerMode); + samplerMode = decl.samplerMode; } if(decl.dim == RESOURCE_DIMENSION_BUFFER && op.operation == OPCODE_LD && decl.declaration == OPCODE_DCL_RESOURCE && decl.operand.type == TYPE_RESOURCE && @@ -3983,7 +3281,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const uint32_t resIndex = (uint32_t)decl.operand.indices[0].index; - byte *data = &global.srvs[resIndex].data[0]; + const byte *data = &global.srvs[resIndex].data[0]; uint32_t offset = global.srvs[resIndex].firstElement; uint32_t numElems = global.srvs[resIndex].numElements; @@ -3998,11 +3296,11 @@ State State::GetNext(GlobalState &global, State quad[4]) const if(srcOpers[0].value.uv[0] < numElems) { - byte *d = data + srcOpers[0].value.uv[0] * fmt.Stride(); + const byte *d = data + srcOpers[0].value.uv[0] * fmt.Stride(); if(fmt.byteWidth == 10) { - uint32_t u = *((uint32_t *)d); + const uint32_t u = *((const uint32_t *)d); if(fmt.fmt == CompType::UInt) { @@ -4026,7 +3324,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const } else if(fmt.byteWidth == 11) { - uint32_t *u = (uint32_t *)d; + const uint32_t *u = (const uint32_t *)d; Vec3f res = ConvertFromR11G11B10(*u); result.value.f.x = res.x; @@ -4036,7 +3334,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const } else if(fmt.byteWidth == 4) { - uint32_t *u = (uint32_t *)d; + const uint32_t *u = (const uint32_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.uv[c] = u[c]; @@ -4045,35 +3343,35 @@ State State::GetNext(GlobalState &global, State quad[4]) const { if(fmt.fmt == CompType::Float) { - uint16_t *u = (uint16_t *)d; + const uint16_t *u = (const uint16_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.fv[c] = ConvertFromHalf(u[c]); } else if(fmt.fmt == CompType::UInt) { - uint16_t *u = (uint16_t *)d; + const uint16_t *u = (const uint16_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.uv[c] = u[c]; } else if(fmt.fmt == CompType::SInt) { - int16_t *in = (int16_t *)d; + const int16_t *in = (const int16_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.iv[c] = in[c]; } else if(fmt.fmt == CompType::UNorm || fmt.fmt == CompType::UNormSRGB) { - uint16_t *u = (uint16_t *)d; + const uint16_t *u = (const uint16_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.fv[c] = float(u[c]) / float(0xffff); } else if(fmt.fmt == CompType::SNorm) { - int16_t *in = (int16_t *)d; + const int16_t *in = (const int16_t *)d; for(int c = 0; c < fmt.numComps; c++) { @@ -4093,28 +3391,28 @@ State State::GetNext(GlobalState &global, State quad[4]) const { if(fmt.fmt == CompType::UInt) { - uint8_t *u = (uint8_t *)d; + const uint8_t *u = (const uint8_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.uv[c] = u[c]; } else if(fmt.fmt == CompType::SInt) { - int8_t *in = (int8_t *)d; + const int8_t *in = (const int8_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.iv[c] = in[c]; } else if(fmt.fmt == CompType::UNorm || fmt.fmt == CompType::UNormSRGB) { - uint8_t *u = (uint8_t *)d; + const uint8_t *u = (const uint8_t *)d; for(int c = 0; c < fmt.numComps; c++) result.value.fv[c] = float(u[c]) / float(0xff); } else if(fmt.fmt == CompType::SNorm) { - int8_t *in = (int8_t *)d; + const int8_t *in = (const int8_t *)d; for(int c = 0; c < fmt.numComps; c++) { @@ -4163,67 +3461,8 @@ State State::GetNext(GlobalState &global, State quad[4]) const decl.operand.indices.size() == 1 && decl.operand.indices[0] == op.operands[2].indices[0]) { resourceDim = decl.dim; - - if(decl.dim == RESOURCE_DIMENSION_TEXTURE1D) - { - texture = "Texture1D"; - texdim = 1; - offsdim = 1; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURE2D) - { - texture = "Texture2D"; - texdim = 2; - offsdim = 2; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURE2DMS) - { - texture = "Texture2DMS"; - texdim = 2; - offsdim = 2; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURE3D) - { - texture = "Texture3D"; - texdim = 3; - offsdim = 3; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURECUBE) - { - texture = "TextureCube"; - texdim = 3; - offsdim = 3; - useOffsets = false; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURE1DARRAY) - { - texture = "Texture1DArray"; - texdim = 2; - offsdim = 1; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURE2DARRAY) - { - texture = "Texture2DArray"; - texdim = 3; - offsdim = 2; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY) - { - texture = "Texture2DMSArray"; - texdim = 3; - offsdim = 2; - } - else if(decl.dim == RESOURCE_DIMENSION_TEXTURECUBEARRAY) - { - texture = "TextureCubeArray"; - texdim = 4; - offsdim = 3; - useOffsets = false; - } - else - { - RDCERR("Unsupported resource type %d in sample operation", decl.dim); - } + resourceRetType = decl.resType[0]; + sampleCount = decl.sampleCount; // doesn't seem like these are ever less than four components, even if the texture is // declared for example. @@ -4233,60 +3472,6 @@ State State::GetNext(GlobalState &global, State quad[4]) const RDCASSERT(decl.resType[0] != RETURN_TYPE_CONTINUED && decl.resType[0] != RETURN_TYPE_UNUSED && decl.resType[0] != RETURN_TYPE_MIXED && decl.resType[0] >= 0 && decl.resType[0] < NUM_RETURN_TYPES); - - char *typeStr[NUM_RETURN_TYPES] = { - "", // enum starts at ==1 - "unorm float", - "snorm float", - "int", - "uint", - "float", - "__", // RETURN_TYPE_MIXED - "double", - "__", // RETURN_TYPE_CONTINUED - "__", // RETURN_TYPE_UNUSED - }; - - // obviously these may be overly optimistic in some cases - // but since we don't know at debug time what the source texture format is - // we just use the fattest one necessary. There's no harm in retrieving at - // higher precision - DXGI_FORMAT fmts[NUM_RETURN_TYPES] = { - DXGI_FORMAT_UNKNOWN, // enum starts at ==1 - DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_UINT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_MIXED - - // should maybe be double, but there is no double texture format anyway! - // spec is unclear but I presume reads are done at most at float - // precision anyway since that's the source, and converted to doubles. - DXGI_FORMAT_R32G32B32A32_FLOAT, - - DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_CONTINUED - DXGI_FORMAT_UNKNOWN, // RETURN_TYPE_UNUSED - }; - - char buf[64] = {0}; - StringFormat::snprintf(buf, 63, "%s4", typeStr[decl.resType[0]]); - - if(retFmt == DXGI_FORMAT_UNKNOWN) - { - funcRet = buf; - - retFmt = fmts[decl.resType[0]]; - } - - if(decl.dim == RESOURCE_DIMENSION_TEXTURE2DMS || - decl.dim == RESOURCE_DIMENSION_TEXTURE2DMSARRAY) - { - if(decl.sampleCount > 0) - StringFormat::snprintf(buf, 63, "%s4, %d", typeStr[decl.resType[0]], decl.sampleCount); - } - - texture += "<"; - texture += buf; - texture += "> t"; } } @@ -4303,12 +3488,7 @@ State State::GetNext(GlobalState &global, State quad[4]) const break; } - std::string sampleProgram; - - char buf[256] = {0}; - char buf2[256] = {0}; - char buf3[256] = {0}; - + ShaderVariable uv = srcOpers[0]; ShaderVariable ddxCalc; ShaderVariable ddyCalc; @@ -4335,520 +3515,72 @@ State State::GetNext(GlobalState &global, State quad[4]) const ddyCalc = srcOpers[4]; } - // serious printf abuse below! - - char *formats[4][2] = { - {"float(%.10f)", "int(%d)"}, - {"float2(%.10f, %.10f)", "int2(%d, %d)"}, - {"float3(%.10f, %.10f, %.10f)", "int3(%d, %d, %d)"}, - {"float4(%.10f, %.10f, %.10f, %.10f)", "int4(%d, %d, %d, %d)"}, - }; - - int texcoordType = 0; - int ddxType = 0; - int ddyType = 0; - - int texdimOffs = 0; - - if(op.operation == OPCODE_SAMPLE || op.operation == OPCODE_SAMPLE_L || - op.operation == OPCODE_SAMPLE_B || op.operation == OPCODE_SAMPLE_D || - op.operation == OPCODE_SAMPLE_C || op.operation == OPCODE_SAMPLE_C_LZ || - op.operation == OPCODE_GATHER4 || op.operation == OPCODE_GATHER4_C || - op.operation == OPCODE_GATHER4_PO || op.operation == OPCODE_GATHER4_PO_C || - op.operation == OPCODE_LOD) - { - // all floats - texcoordType = ddxType = ddyType = 0; - } - else if(op.operation == OPCODE_LD) - { - // int address, one larger than texdim (to account for mip/slice parameter) - texdimOffs = 1; - texcoordType = 1; - - if(texdim == 4) - { - RDCERR("Unexpectedly large texture in load operation"); - } - } - else if(op.operation == OPCODE_LD_MS) - { - texcoordType = 1; - - if(texdim == 4) - { - RDCERR("Unexpectedly large texture in load operation"); - } - } - - ShaderVariable uv = srcOpers[0]; - - for(uint32_t i = 0; i < ddxCalc.columns; i++) - { - if(ddxType == 0 && (_isnan(ddxCalc.value.fv[i]) || !_finite(ddxCalc.value.fv[i]))) - { - RDCWARN("NaN or Inf in texlookup"); - ddxCalc.value.fv[i] = 0.0f; - - device->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, - MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\nNaN or Inf found in " - "texture lookup ddx - using 0.0 instead", - s.nextInstruction - 1, op.str.c_str())); - } - if(ddyType == 0 && (_isnan(ddyCalc.value.fv[i]) || !_finite(ddyCalc.value.fv[i]))) - { - RDCWARN("NaN or Inf in texlookup"); - ddyCalc.value.fv[i] = 0.0f; - - device->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, - MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\nNaN or Inf found in " - "texture lookup ddy - using 0.0 instead", - s.nextInstruction - 1, op.str.c_str())); - } - } - - for(uint32_t i = 0; i < uv.columns; i++) - { - if(texcoordType == 0 && (_isnan(uv.value.fv[i]) || !_finite(uv.value.fv[i]))) - { - RDCWARN("NaN or Inf in texlookup"); - uv.value.fv[i] = 0.0f; - - device->AddDebugMessage(MessageCategory::Shaders, MessageSeverity::High, - MessageSource::RuntimeWarning, - StringFormat::Fmt("Shader debugging %d: %s\nNaN or Inf found in " - "texture lookup uv - using 0.0 instead", - s.nextInstruction - 1, op.str.c_str())); - } - } - - // because of unions in .value we can pass the float versions and printf will interpret it as - // the right type according to formats - if(texcoordType == 0) - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x, uv.value.f.y, uv.value.f.z, uv.value.f.w); - else - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.i.x, uv.value.i.y, uv.value.i.z, uv.value.i.w); - - if(ddxType == 0) - StringFormat::snprintf(buf2, 255, formats[offsdim + texdimOffs - 1][ddxType], - ddxCalc.value.f.x, ddxCalc.value.f.y, ddxCalc.value.f.z, - ddxCalc.value.f.w); - else - StringFormat::snprintf(buf2, 255, formats[offsdim + texdimOffs - 1][ddxType], - ddxCalc.value.i.x, ddxCalc.value.i.y, ddxCalc.value.i.z, - ddxCalc.value.i.w); - - if(ddyType == 0) - StringFormat::snprintf(buf3, 255, formats[offsdim + texdimOffs - 1][ddyType], - ddyCalc.value.f.x, ddyCalc.value.f.y, ddyCalc.value.f.z, - ddyCalc.value.f.w); - else - StringFormat::snprintf(buf3, 255, formats[offsdim + texdimOffs - 1][ddyType], - ddyCalc.value.i.x, ddyCalc.value.i.y, ddyCalc.value.i.z, - ddyCalc.value.i.w); - - std::string texcoords = buf; - std::string ddx = buf2; - std::string ddy = buf3; - - if(op.operation == OPCODE_LD_MS) - { - StringFormat::snprintf(buf, 255, formats[0][1], srcOpers[2].value.i.x); - } - - std::string sampleIdx = buf; - - std::string offsets = ""; - - if(useOffsets) - { - if(offsdim == 1) - StringFormat::snprintf(buf, 255, ", int(%d)", op.texelOffset[0]); - if(offsdim == 2) - StringFormat::snprintf(buf, 255, ", int2(%d, %d)", op.texelOffset[0], op.texelOffset[1]); - if(offsdim == 3) - StringFormat::snprintf(buf, 255, ", int3(%d, %d, %d)", op.texelOffset[0], - op.texelOffset[1], op.texelOffset[2]); - // texdim == 4 is cube arrays, no offset supported - - offsets = buf; - } - - std::string swizzle = "."; - - char elems[] = "xyzw"; - - for(int i = 0; i < 4; i++) - { - if(op.operands[2].comps[i] == 0xff) - swizzle += "x"; - else - swizzle += elems[op.operands[2].comps[i]]; - } - - const char *channel = ""; - if(op.operation == OPCODE_GATHER4 || op.operation == OPCODE_GATHER4_C || - op.operation == OPCODE_GATHER4_PO || op.operation == OPCODE_GATHER4_PO_C) - { - switch(op.operands[3].comps[0]) - { - case 0: channel = "Red"; break; - case 1: channel = "Green"; break; - case 2: channel = "Blue"; break; - case 3: channel = "Alpha"; break; - } - } - - std::string vsProgram = "float4 main(uint id : SV_VertexID) : SV_Position {\n"; - vsProgram += "return float4((id == 2) ? 3.0f : -1.0f, (id == 0) ? -3.0f : 1.0f, 0.5, 1.0);\n"; - vsProgram += "}"; - UINT texSlot = (UINT)op.operands[2].indices[0].index; - UINT sampSlot = 0; + UINT samplerSlot = 0; for(size_t i = 0; i < op.operands.size(); i++) { const ASMOperand &operand = op.operands[i]; if(operand.type == OperandType::TYPE_SAMPLER) - sampSlot = (UINT)operand.indices[0].index; + samplerSlot = (UINT)operand.indices[0].index; } - if(op.operation == OPCODE_SAMPLE || op.operation == OPCODE_SAMPLE_B || - op.operation == OPCODE_SAMPLE_D) + int multisampleIndex = srcOpers[2].value.i.x; + float lodOrCompareValue = srcOpers[3].value.f.x; + if(op.operation == OPCODE_GATHER4_PO_C) + lodOrCompareValue = srcOpers[4].value.f.x; + + uint8_t swizzle[4] = {0}; + for(int i = 0; i < 4; i++) { - sampleProgram = texture + " : register(t0);\n" + sampler + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += - "t.SampleGrad(s, " + texcoords + ", " + ddx + ", " + ddy + offsets + ")" + swizzle + ";"; - sampleProgram += "\n}\n"; + if(op.operands[2].comps[i] == 0xff) + swizzle[i] = 0; + else + swizzle[i] = op.operands[2].comps[i]; } - else if(op.operation == OPCODE_SAMPLE_L) + + GatherChannel gatherChannel = GatherChannel::Red; + if(op.operation == OPCODE_GATHER4 || op.operation == OPCODE_GATHER4_C || + op.operation == OPCODE_GATHER4_PO || op.operation == OPCODE_GATHER4_PO_C) { - // lod selection - StringFormat::snprintf(buf, 255, "%.10f", srcOpers[3].value.f.x); - - sampleProgram = texture + " : register(t0);\n" + sampler + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += - "t.SampleLevel(s, " + texcoords + ", " + buf + offsets + ")" + swizzle + ";"; - sampleProgram += "\n}\n"; + gatherChannel = (GatherChannel)op.operands[3].comps[0]; } - else if(op.operation == OPCODE_SAMPLE_C || op.operation == OPCODE_LOD) - { - // these operations need derivatives but have no hlsl function to call to provide them, so - // we fake it in the vertex shader - - std::string uvDim = "1"; - uvDim[0] += char(texdim + texdimOffs - 1); - - vsProgram = "void main(uint id : SV_VertexID, out float4 pos : SV_Position, out float" + - uvDim + " uv : uvs) {\n"; - - StringFormat::snprintf( - buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x + ddyCalc.value.f.x * 2.0f, uv.value.f.y + ddyCalc.value.f.y * 2.0f, - uv.value.f.z + ddyCalc.value.f.z * 2.0f, uv.value.f.w + ddyCalc.value.f.w * 2.0f); - - vsProgram += "if(id == 0) uv = " + std::string(buf) + ";\n"; - - StringFormat::snprintf(buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x, uv.value.f.y, uv.value.f.z, uv.value.f.w); - - vsProgram += "if(id == 1) uv = " + std::string(buf) + ";\n"; - - StringFormat::snprintf( - buf, 255, formats[texdim + texdimOffs - 1][texcoordType], - uv.value.f.x + ddxCalc.value.f.x * 2.0f, uv.value.f.y + ddxCalc.value.f.y * 2.0f, - uv.value.f.z + ddxCalc.value.f.z * 2.0f, uv.value.f.w + ddxCalc.value.f.w * 2.0f); - - vsProgram += "if(id == 2) uv = " + std::string(buf) + ";\n"; - - vsProgram += - "pos = float4((id == 2) ? 3.0f : -1.0f, (id == 0) ? -3.0f : 1.0f, 0.5, 1.0);\n"; - vsProgram += "}"; - - if(op.operation == OPCODE_SAMPLE_C) - { - // comparison value - StringFormat::snprintf(buf, 255, "%.10f", srcOpers[3].value.f.x); - - sampleProgram = texture + " : register(t0);\n" + sampler + " : register(s0);\n\n"; - sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + - " uv : uvs) : SV_Target0\n{\n"; - sampleProgram += - "return t.SampleCmpLevelZero(s, uv, " + std::string(buf) + offsets + ").xxxx;"; - sampleProgram += "\n}\n"; - } - else if(op.operation == OPCODE_LOD) - { - sampleProgram = texture + " : register(t0);\n" + sampler + " : register(s0);\n\n"; - sampleProgram += funcRet + " main(float4 pos : SV_Position, float" + uvDim + - " uv : uvs) : SV_Target0\n{\n"; - sampleProgram += - "return float4(t.CalculateLevelOfDetail(s, uv), t.CalculateLevelOfDetailUnclamped(s, " - "uv), 0.0f, 0.0f);"; - sampleProgram += "\n}\n"; - } - } - else if(op.operation == OPCODE_SAMPLE_C_LZ) - { - // comparison value - StringFormat::snprintf(buf, 255, "%.10f", srcOpers[3].value.f.x); - - sampleProgram = texture + " : register(t0);\n" + sampler + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += - "t.SampleCmpLevelZero(s, " + texcoords + ", " + buf + offsets + ")" + swizzle + ";"; - sampleProgram += "\n}\n"; - } - else if(op.operation == OPCODE_LD) - { - sampleProgram = texture + " : register(t0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.Load(" + texcoords + offsets + ")" + swizzle + ";"; - sampleProgram += "\n}\n"; - } - else if(op.operation == OPCODE_LD_MS) - { - sampleProgram = texture + " : register(t0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.Load(" + texcoords + ", " + sampleIdx + offsets + ")" + swizzle + ";"; - sampleProgram += "\n}\n"; - } - else if(op.operation == OPCODE_GATHER4 || op.operation == OPCODE_GATHER4_PO) - { - sampleProgram = texture + " : register(t0);\n" + sampler + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += - "t.Gather" + std::string(channel) + "(s, " + texcoords + offsets + ")" + swizzle + ";"; - sampleProgram += "\n}\n"; - } - else if(op.operation == OPCODE_GATHER4_C || op.operation == OPCODE_GATHER4_PO_C) - { - // comparison value - if(op.operation == OPCODE_GATHER4_C) - StringFormat::snprintf(buf, 255, ", %.10f", srcOpers[3].value.f.x); - else if(op.operation == OPCODE_GATHER4_PO_C) - StringFormat::snprintf(buf, 255, ", %.10f", srcOpers[4].value.f.x); - - sampleProgram = texture + " : register(t0);\n" + sampler + " : register(s0);\n\n"; - sampleProgram += funcRet + " main() : SV_Target0\n{\nreturn "; - sampleProgram += "t.GatherCmp" + std::string(channel) + "(s, " + texcoords + buf + offsets + - ")" + swizzle + ";"; - sampleProgram += "\n}\n"; - } - - ID3D11VertexShader *vs = - device->GetShaderCache()->MakeVShader(vsProgram.c_str(), "main", "vs_5_0"); - ID3D11PixelShader *ps = - device->GetShaderCache()->MakePShader(sampleProgram.c_str(), "main", "ps_5_0"); - - ID3D11DeviceContext *context = NULL; - - device->GetImmediateContext(&context); - - // back up SRV/sampler on PS slot 0 - - ID3D11ShaderResourceView *prevSRV = NULL; - ID3D11SamplerState *prevSamp = NULL; - - context->PSGetShaderResources(0, 1, &prevSRV); - context->PSGetSamplers(0, 1, &prevSamp); - - ID3D11ShaderResourceView *usedSRV = NULL; - ID3D11SamplerState *usedSamp = NULL; - - // fetch SRV and sampler from the shader stage we're debugging that this opcode wants to - // load from - - if(dxbc->m_Type == D3D11_ShaderType_Vertex) - context->VSGetShaderResources(texSlot, 1, &usedSRV); - else if(dxbc->m_Type == D3D11_ShaderType_Hull) - context->HSGetShaderResources(texSlot, 1, &usedSRV); - else if(dxbc->m_Type == D3D11_ShaderType_Domain) - context->DSGetShaderResources(texSlot, 1, &usedSRV); - else if(dxbc->m_Type == D3D11_ShaderType_Geometry) - context->GSGetShaderResources(texSlot, 1, &usedSRV); - else if(dxbc->m_Type == D3D11_ShaderType_Pixel) - context->PSGetShaderResources(texSlot, 1, &usedSRV); - else if(dxbc->m_Type == D3D11_ShaderType_Compute) - context->CSGetShaderResources(texSlot, 1, &usedSRV); - - if(dxbc->m_Type == D3D11_ShaderType_Vertex) - context->VSGetSamplers(sampSlot, 1, &usedSamp); - else if(dxbc->m_Type == D3D11_ShaderType_Hull) - context->HSGetSamplers(sampSlot, 1, &usedSamp); - else if(dxbc->m_Type == D3D11_ShaderType_Domain) - context->DSGetSamplers(sampSlot, 1, &usedSamp); - else if(dxbc->m_Type == D3D11_ShaderType_Geometry) - context->GSGetSamplers(sampSlot, 1, &usedSamp); - else if(dxbc->m_Type == D3D11_ShaderType_Pixel) - context->PSGetSamplers(sampSlot, 1, &usedSamp); - else if(dxbc->m_Type == D3D11_ShaderType_Compute) - context->CSGetSamplers(sampSlot, 1, &usedSamp); - - // set onto PS while we perform the sample - context->PSSetShaderResources(0, 1, &usedSRV); - context->PSSetSamplers(0, 1, &usedSamp); - - context->IASetInputLayout(NULL); - context->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - - context->VSSetShader(vs, NULL, 0); - context->PSSetShader(ps, NULL, 0); // for bias instruction we can't do a SampleGradBias, so add the bias into the sampler state. + float samplerBias = 0.0f; if(op.operation == OPCODE_SAMPLE_B) { - ID3D11SamplerState *samp = NULL; - - context->PSGetSamplers((UINT)srcOpers[2].value.u.x, 1, &samp); - - RDCASSERT(samp); - - D3D11_SAMPLER_DESC desc; - - samp->GetDesc(&desc); - - SAFE_RELEASE(samp); - - desc.MipLODBias = RDCCLAMP(desc.MipLODBias + srcOpers[3].value.f.x, -15.99f, 15.99f); - - ID3D11SamplerState *replacementSamp = NULL; - - HRESULT hr = device->CreateSamplerState(&desc, &replacementSamp); - - if(FAILED(hr)) - { - RDCERR("Failed to create new sampler state in debugging HRESULT: %s", ToStr(hr).c_str()); - } - else - { - context->PSSetSamplers(0, 1, &replacementSamp); - - SAFE_RELEASE(replacementSamp); - } + samplerSlot = (UINT)srcOpers[2].value.u.x; + samplerBias = srcOpers[3].value.f.x; } - D3D11_VIEWPORT view = {0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f}; - context->RSSetViewports(1, &view); + SampleGatherResourceData resourceData; + resourceData.dim = resourceDim; + resourceData.retType = resourceRetType; + resourceData.sampleCount = sampleCount; + resourceData.slot = texSlot; - context->GSSetShader(NULL, NULL, 0); - context->DSSetShader(NULL, NULL, 0); - context->HSSetShader(NULL, NULL, 0); - context->CSSetShader(NULL, NULL, 0); - - context->SOSetTargets(0, NULL, NULL); - - context->RSSetState(NULL); - context->OMSetBlendState(NULL, NULL, (UINT)~0); - context->OMSetDepthStencilState(NULL, 0); - - ID3D11RenderTargetView *rtv = NULL; - - ID3D11Texture2D *rtTex = NULL; - ID3D11Texture2D *copyTex = NULL; - - D3D11_TEXTURE2D_DESC tdesc; - - RDCASSERT(retFmt != DXGI_FORMAT_UNKNOWN); - - tdesc.ArraySize = 1; - tdesc.BindFlags = D3D11_BIND_RENDER_TARGET; - tdesc.CPUAccessFlags = 0; - tdesc.Format = retFmt; - tdesc.Width = 1; - tdesc.Height = 1; - tdesc.MipLevels = 0; - tdesc.MiscFlags = 0; - tdesc.SampleDesc.Count = 1; - tdesc.SampleDesc.Quality = 0; - tdesc.Usage = D3D11_USAGE_DEFAULT; - - HRESULT hr = S_OK; - - hr = device->CreateTexture2D(&tdesc, NULL, &rtTex); - - if(FAILED(hr)) - { - RDCERR("Failed to create RT tex HRESULT: %s", ToStr(hr).c_str()); - return s; - } - - tdesc.BindFlags = 0; - tdesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - tdesc.Usage = D3D11_USAGE_STAGING; - - hr = device->CreateTexture2D(&tdesc, NULL, ©Tex); - - if(FAILED(hr)) - { - RDCERR("Failed to create copy tex HRESULT: %s", ToStr(hr).c_str()); - return s; - } - - D3D11_RENDER_TARGET_VIEW_DESC rtDesc; - - rtDesc.Format = retFmt; - rtDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtDesc.Texture2D.MipSlice = 0; - - hr = device->CreateRenderTargetView(rtTex, &rtDesc, &rtv); - - if(FAILED(hr)) - { - RDCERR("Failed to create rt rtv HRESULT: %s", ToStr(hr).c_str()); - return s; - } - - context->OMSetRenderTargetsAndUnorderedAccessViews(1, &rtv, NULL, 0, 0, NULL, NULL); - context->Draw(3, 0); - - context->CopyResource(copyTex, rtTex); - - D3D11_MAPPED_SUBRESOURCE mapped; - hr = context->Map(copyTex, 0, D3D11_MAP_READ, 0, &mapped); - - if(FAILED(hr)) - { - RDCERR("Failed to map results HRESULT: %s", ToStr(hr).c_str()); - return s; - } + SampleGatherSamplerData samplerData; + samplerData.mode = samplerMode; + samplerData.slot = samplerSlot; + samplerData.bias = samplerBias; ShaderVariable lookupResult("tex", 0.0f, 0.0f, 0.0f, 0.0f); + if(apiWrapper->CalculateSampleGather(op.operation, resourceData, samplerData, uv, ddxCalc, + ddyCalc, op.texelOffset, multisampleIndex, + lodOrCompareValue, swizzle, gatherChannel, + op.str.c_str(), lookupResult)) + { + // should be a better way of doing this + if(op.operands[0].comps[1] == 0xff) + lookupResult.value.iv[0] = lookupResult.value.iv[op.operands[0].comps[0]]; - memcpy(lookupResult.value.iv, mapped.pData, sizeof(uint32_t) * 4); - - context->Unmap(copyTex, 0); - - SAFE_RELEASE(rtTex); - SAFE_RELEASE(copyTex); - SAFE_RELEASE(rtv); - SAFE_RELEASE(vs); - SAFE_RELEASE(ps); - - // restore whatever was on PS slot 0 before we messed with it - - context->PSSetShaderResources(0, 1, &prevSRV); - context->PSSetSamplers(0, 1, &prevSamp); - - SAFE_RELEASE(context); - - SAFE_RELEASE(prevSRV); - SAFE_RELEASE(prevSamp); - - SAFE_RELEASE(usedSRV); - SAFE_RELEASE(usedSamp); - - // should be a better way of doing this - if(op.operands[0].comps[1] == 0xff) - lookupResult.value.iv[0] = lookupResult.value.iv[op.operands[0].comps[0]]; - - s.SetDst(op.operands[0], op, lookupResult); + s.SetDst(op.operands[0], op, lookupResult); + } + else + { + return s; + } break; } diff --git a/renderdoc/driver/shaders/dxbc/dxbc_debug.h b/renderdoc/driver/shaders/dxbc/dxbc_debug.h index 2e2f9154f..dcbef844e 100644 --- a/renderdoc/driver/shaders/dxbc/dxbc_debug.h +++ b/renderdoc/driver/shaders/dxbc/dxbc_debug.h @@ -147,6 +147,55 @@ public: std::map sampleEvalCache; }; +struct SampleGatherResourceData +{ + DXBC::ResourceDimension dim; + DXBC::ResourceRetType retType; + int sampleCount; + UINT slot; +}; + +struct SampleGatherSamplerData +{ + DXBC::SamplerMode mode; + UINT slot; + float bias; +}; + +enum class GatherChannel : uint8_t +{ + Red = 0, + Green = 1, + Blue = 2, + Alpha = 3, +}; + +class DebugAPIWrapper +{ +public: + virtual void SetCurrentInstruction(uint32_t instruction) = 0; + virtual void AddDebugMessage(MessageCategory c, MessageSeverity sv, MessageSource src, + std::string d) = 0; + + virtual bool CalculateMathIntrinsic(DXBC::OpcodeType opcode, const ShaderVariable &input, + ShaderVariable &output1, ShaderVariable &output2) = 0; + + virtual ShaderVariable GetSampleInfo(DXBC::OperandType type, bool isAbsoluteResource, UINT slot, + const char *opString) = 0; + + virtual ShaderVariable GetBufferInfo(DXBC::OperandType type, UINT slot, const char *opString) = 0; + virtual ShaderVariable GetResourceInfo(DXBC::OperandType type, UINT slot, uint32_t mipLevel, + int &dim) = 0; + + virtual bool CalculateSampleGather(DXBC::OpcodeType opcode, SampleGatherResourceData resourceData, + SampleGatherSamplerData samplerData, ShaderVariable uv, + ShaderVariable ddxCalc, ShaderVariable ddyCalc, + const int texelOffsets[3], int multisampleIndex, + float lodOrCompareValue, const uint8_t swizzle[4], + GatherChannel gatherChannel, const char *opString, + ShaderVariable &output) = 0; +}; + class State : public ShaderDebugState { public: @@ -158,10 +207,9 @@ public: done = false; trace = NULL; dxbc = NULL; - device = NULL; RDCEraseEl(semantics); } - State(int quadIdx, const ShaderDebugTrace *t, DXBC::DXBCFile *f, WrappedID3D11Device *d) + State(int quadIdx, const ShaderDebugTrace *t, DXBC::DXBCFile *f) { quadIndex = quadIdx; nextInstruction = 0; @@ -169,7 +217,6 @@ public: done = false; trace = t; dxbc = f; - device = d; RDCEraseEl(semantics); } @@ -192,7 +239,7 @@ public: void Init(); bool Finished() const; - State GetNext(GlobalState &global, State quad[4]) const; + State GetNext(GlobalState &global, DebugAPIWrapper *apiWrapper, State quad[4]) const; private: // index in the pixel quad @@ -223,7 +270,6 @@ private: DXBC::DXBCFile *dxbc; const ShaderDebugTrace *trace; - WrappedID3D11Device *device; }; }; // namespace ShaderDebug