summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/render-test/d3d-util.h6
-rw-r--r--tools/render-test/main.cpp12
-rw-r--r--tools/render-test/options.cpp27
-rw-r--r--tools/render-test/options.h3
-rw-r--r--tools/render-test/render-d3d12.cpp542
-rw-r--r--tools/render-test/resource-d3d12.h10
-rw-r--r--tools/render-test/shader-input-layout.h131
-rw-r--r--tools/slang-test/main.cpp153
-rw-r--r--tools/slang-test/render-api-util.cpp210
-rw-r--r--tools/slang-test/render-api-util.h61
-rw-r--r--tools/slang-test/slang-test.vcxproj2
-rw-r--r--tools/slang-test/slang-test.vcxproj.filters6
12 files changed, 850 insertions, 313 deletions
diff --git a/tools/render-test/d3d-util.h b/tools/render-test/d3d-util.h
index 95ccf4b18..6ac39aefb 100644
--- a/tools/render-test/d3d-util.h
+++ b/tools/render-test/d3d-util.h
@@ -26,8 +26,8 @@ class D3DUtil
};
enum UsageFlag
{
- USAGE_FLAG_MULTI_SAMPLE = 0x1,
- USAGE_FLAG_SRV = 0x2,
+ USAGE_FLAG_MULTI_SAMPLE = 0x1, ///< If set will be used form multi sampling (such as MSAA)
+ USAGE_FLAG_SRV = 0x2, ///< If set means will be used as a shader resource view (SRV)
};
/// Get primitive topology as D3D primitive topology
@@ -41,9 +41,9 @@ class D3DUtil
/// Definition of the HLSL-to-bytecode compilation logic.
static Slang::Result compileHLSLShader(char const* sourcePath, char const* source, char const* entryPointName, char const* dxProfileName, Slang::ComPtr<ID3DBlob>& shaderBlobOut);
+ /// Given a slang pixel format returns the equivalent DXGI_ pixel format. If the format is not known, will return DXGI_FORMAT_UNKNOWN
static DXGI_FORMAT getMapFormat(Format format);
-
/// Given the usage, flags, and format will return the most suitable format. Will return DXGI_UNKNOWN if combination is not possible
static DXGI_FORMAT calcFormat(UsageType usage, DXGI_FORMAT format);
/// Calculate appropriate format for creating a buffer for usage and flags
diff --git a/tools/render-test/main.cpp b/tools/render-test/main.cpp
index 6233b7617..12160ae78 100644
--- a/tools/render-test/main.cpp
+++ b/tools/render-test/main.cpp
@@ -41,12 +41,13 @@ struct Vertex
float uv[2];
};
-static const int kVertexCount = 3;
-static const Vertex kVertexData[kVertexCount] = {
+static const Vertex kVertexData[] =
+{
{ { 0, 0, 0.5 }, {1, 0, 0} , {0, 0} },
{ { 0, 1, 0.5 }, {0, 0, 1} , {1, 0} },
{ { 1, 0, 0.5 }, {0, 1, 0} , {1, 1} },
};
+static const int kVertexCount = SLANG_COUNT_OF(kVertexData);
using namespace Slang;
@@ -79,7 +80,6 @@ class RenderTestApp
RefPtr<BindingState> m_bindingState;
ShaderInputLayout m_shaderInputLayout;
-
};
// Entry point name to use for vertex/fragment shader
@@ -116,13 +116,13 @@ SlangResult RenderTestApp::initialize(Renderer* renderer, ShaderCompiler* shader
// Input Assembler (IA)
- InputElementDesc inputElements[] = {
+ const InputElementDesc inputElements[] = {
{ "A", 0, Format::RGB_Float32, offsetof(Vertex, position) },
{ "A", 1, Format::RGB_Float32, offsetof(Vertex, color) },
{ "A", 2, Format::RG_Float32, offsetof(Vertex, uv) },
};
- m_inputLayout = renderer->createInputLayout(&inputElements[0], sizeof(inputElements)/sizeof(inputElements[0]));
+ m_inputLayout = renderer->createInputLayout(inputElements, SLANG_COUNT_OF(inputElements));
if(!m_inputLayout)
return SLANG_FAIL;
@@ -437,7 +437,7 @@ SlangResult innerMain(int argc, char** argv)
return SLANG_OK;
}
-} // renderer_test
+} // namespace renderer_test
int main(int argc, char** argv)
{
diff --git a/tools/render-test/options.cpp b/tools/render-test/options.cpp
index 30aeca6b0..bdf635620 100644
--- a/tools/render-test/options.cpp
+++ b/tools/render-test/options.cpp
@@ -10,6 +10,12 @@ namespace renderer_test {
Options gOptions;
+// Only set it, if the
+void setDefaultRendererID(RendererID id)
+{
+ gOptions.rendererID = (gOptions.rendererID == RendererID::NONE) ? id : gOptions.rendererID;
+}
+
SlangResult parseOptions(int* argc, char** argv)
{
int argCount = *argc;
@@ -54,32 +60,32 @@ SlangResult parseOptions(int* argc, char** argv)
}
else if( strcmp(arg, "-hlsl") == 0 )
{
- gOptions.rendererID = RendererID::D3D11;
+ setDefaultRendererID( RendererID::D3D11);
gOptions.inputLanguageID = InputLanguageID::Native;
}
else if( strcmp(arg, "-glsl") == 0 )
{
- gOptions.rendererID = RendererID::GL;
+ setDefaultRendererID(RendererID::GL);
gOptions.inputLanguageID = InputLanguageID::Native;
}
else if( strcmp(arg, "-hlsl-rewrite") == 0 )
{
- gOptions.rendererID = RendererID::D3D11;
+ setDefaultRendererID(RendererID::D3D11);
gOptions.inputLanguageID = InputLanguageID::NativeRewrite;
}
else if( strcmp(arg, "-glsl-rewrite") == 0 )
{
- gOptions.rendererID = RendererID::GL;
+ setDefaultRendererID(RendererID::GL);
gOptions.inputLanguageID = InputLanguageID::NativeRewrite;
}
else if( strcmp(arg, "-slang") == 0 )
{
- gOptions.rendererID = RendererID::D3D11;
+ setDefaultRendererID(RendererID::D3D11);
gOptions.inputLanguageID = InputLanguageID::Slang;
}
else if( strcmp(arg, "-glsl-cross") == 0 )
{
- gOptions.rendererID = RendererID::GL;
+ setDefaultRendererID(RendererID::GL);
gOptions.inputLanguageID = InputLanguageID::Slang;
}
else if( strcmp(arg, "-xslang") == 0 )
@@ -120,6 +126,15 @@ SlangResult parseOptions(int* argc, char** argv)
{
gOptions.rendererID = RendererID::D3D12;
}
+ else if(strcmp(arg, "-gl") == 0)
+ {
+ gOptions.rendererID = RendererID::GL;
+ }
+ else if (strcmp(arg, "-d3d11") == 0
+ || strcmp(arg, "-dx11") == 0)
+ {
+ gOptions.rendererID = RendererID::D3D11;
+ }
else
{
fprintf(stderr, "unknown option '%s'\n", arg);
diff --git a/tools/render-test/options.h b/tools/render-test/options.h
index a33172c6b..8dbff76ea 100644
--- a/tools/render-test/options.h
+++ b/tools/render-test/options.h
@@ -12,6 +12,7 @@ typedef uintptr_t UInt;
enum class RendererID
{
+ NONE,
D3D11,
D3D12,
GL,
@@ -50,7 +51,7 @@ struct Options
char const* outputPath = nullptr;
ShaderProgramType shaderType = ShaderProgramType::Graphics;
- RendererID rendererID;
+ RendererID rendererID = RendererID::NONE;
InputLanguageID inputLanguageID = InputLanguageID::Slang;
char const* slangArgs[kMaxSlangArgs];
diff --git a/tools/render-test/render-d3d12.cpp b/tools/render-test/render-d3d12.cpp
index 6d79cb8e5..9d4fdf03c 100644
--- a/tools/render-test/render-d3d12.cpp
+++ b/tools/render-test/render-d3d12.cpp
@@ -455,7 +455,7 @@ Result D3D12Renderer::createInputSampler(const InputSamplerDesc& inputDesc, D3D1
return SLANG_OK;
}
-static void _initSrvDesc(const D3D12_RESOURCE_DESC& desc, DXGI_FORMAT pixelFormat, D3D12_SHADER_RESOURCE_VIEW_DESC& descOut)
+static void _initSrvDesc(const InputTextureDesc& inputDesc, const D3D12_RESOURCE_DESC& desc, DXGI_FORMAT pixelFormat, D3D12_SHADER_RESOURCE_VIEW_DESC& descOut)
{
// create SRV
descOut = D3D12_SHADER_RESOURCE_VIEW_DESC();
@@ -477,17 +477,39 @@ static void _initSrvDesc(const D3D12_RESOURCE_DESC& desc, DXGI_FORMAT pixelForma
descOut.Texture2D.PlaneSlice = 0;
descOut.Texture2D.ResourceMinLODClamp = 0.0f;
}
- else if (desc.DepthOrArraySize == 6)
+ else if (inputDesc.isCube)
{
- descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
+ if (inputDesc.arrayLength > 1)
+ {
+ descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBEARRAY;
- descOut.TextureCube.MipLevels = desc.MipLevels;
- descOut.TextureCube.MostDetailedMip = 0;
- descOut.TextureCube.ResourceMinLODClamp = 0;
+ descOut.TextureCubeArray.NumCubes = inputDesc.arrayLength;
+ descOut.TextureCubeArray.First2DArrayFace = 0;
+ descOut.TextureCubeArray.MipLevels = desc.MipLevels;
+ descOut.TextureCubeArray.MostDetailedMip = 0;
+ descOut.TextureCubeArray.ResourceMinLODClamp = 0;
+ }
+ else
+ {
+ descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
+
+ descOut.TextureCube.MipLevels = desc.MipLevels;
+ descOut.TextureCube.MostDetailedMip = 0;
+ descOut.TextureCube.ResourceMinLODClamp = 0;
+ }
}
else
{
- descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY;
+ assert(desc.DepthOrArraySize > 1);
+
+ switch (desc.Dimension)
+ {
+ case D3D12_RESOURCE_DIMENSION_TEXTURE1D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE1DARRAY; break;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE2D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2DARRAY; break;
+ case D3D12_RESOURCE_DIMENSION_TEXTURE3D: descOut.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE3D; break;
+
+ default: assert(!"Unknown dimension");
+ }
descOut.Texture2DArray.ArraySize = desc.DepthOrArraySize;
descOut.Texture2DArray.MostDetailedMip = 0;
@@ -498,7 +520,7 @@ static void _initSrvDesc(const D3D12_RESOURCE_DESC& desc, DXGI_FORMAT pixelForma
}
}
-void _initBufferResourceDesc(size_t bufferSize, D3D12_RESOURCE_DESC& out)
+static void _initBufferResourceDesc(size_t bufferSize, D3D12_RESOURCE_DESC& out)
{
out = {};
@@ -540,7 +562,10 @@ Result D3D12Renderer::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, cons
heapProps.CreationNodeMask = 1;
heapProps.VisibleNodeMask = 1;
- SLANG_RETURN_ON_FAIL(uploadResource.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
+ D3D12_RESOURCE_DESC uploadResourceDesc(resourceDesc);
+ uploadResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+
+ SLANG_RETURN_ON_FAIL(uploadResource.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, uploadResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
}
if (srcData)
@@ -572,13 +597,16 @@ Result D3D12Renderer::createBuffer(const D3D12_RESOURCE_DESC& resourceDesc, cons
Result D3D12Renderer::createTexture(const InputTextureDesc& inputDesc, const TextureData& texData, D3D12Resource& resourceOut)
{
- // generateTextureData(texData, inputDesc);
+ // Description of uploading on Dx12
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/dn899215%28v=vs.85%29.aspx
const DXGI_FORMAT pixelFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
const int numMipMaps = texData.mipLevels;
const int width = inputDesc.size;
- const int height = width;
+ // If the dimension is 1, then we have no height
+ const int height = (inputDesc.dimension <= 1) ? 1 : width;
+ const int depth = (inputDesc.dimension <= 2) ? 1 : width;
// Setup desc
D3D12_RESOURCE_DESC resourceDesc;
@@ -587,7 +615,8 @@ Result D3D12Renderer::createTexture(const InputTextureDesc& inputDesc, const Tex
resourceDesc.Format = pixelFormat;
resourceDesc.Width = width;
resourceDesc.Height = height;
- resourceDesc.DepthOrArraySize = texData.arraySize;
+ resourceDesc.DepthOrArraySize = (depth > 1) ? depth : texData.arraySize;
+
resourceDesc.MipLevels = numMipMaps;
resourceDesc.SampleDesc.Count = 1;
resourceDesc.SampleDesc.Quality = 0;
@@ -602,7 +631,22 @@ Result D3D12Renderer::createTexture(const InputTextureDesc& inputDesc, const Tex
case 3: resourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE3D; break;
default: return SLANG_FAIL;
}
-
+
+ // Create the target resource
+ {
+ D3D12_HEAP_PROPERTIES heapProps;
+
+ heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 1;
+ heapProps.VisibleNodeMask = 1;
+
+ SLANG_RETURN_ON_FAIL(resourceOut.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
+
+ resourceOut.setDebugName(L"Texture");
+ }
+
// Calculate the layout
List<D3D12_PLACED_SUBRESOURCE_FOOTPRINT> layouts;
layouts.SetSize(numMipMaps);
@@ -614,108 +658,131 @@ Result D3D12Renderer::createTexture(const InputTextureDesc& inputDesc, const Tex
UInt64 requiredSize = 0;
m_device->GetCopyableFootprints(&resourceDesc, 0, texData.mipLevels, 0, layouts.begin(), mipNumRows.begin(), mipRowSizeInBytes.begin(), &requiredSize);
+#if 0
List<D3D12_SUBRESOURCE_DATA> subData;
subData.SetSize(numMipMaps);
// Zero it all initially
::memset(subData.Buffer(), 0, numMipMaps * sizeof(D3D12_SUBRESOURCE_DATA));
-
- // Create the upload texture
- D3D12Resource uploadTexture;
- {
- D3D12_HEAP_PROPERTIES heapProps;
-
- heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
+#endif
- D3D12_RESOURCE_DESC uploadResourceDesc;
-
- uploadResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
- uploadResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
- uploadResourceDesc.Width = requiredSize;
- uploadResourceDesc.Height = 1;
- uploadResourceDesc.DepthOrArraySize = 1;
- uploadResourceDesc.MipLevels = 1;
- uploadResourceDesc.SampleDesc.Count = 1;
- uploadResourceDesc.SampleDesc.Quality = 0;
- uploadResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
- uploadResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
- uploadResourceDesc.Alignment = 0;
+ //
+ assert(texData.dataBuffer.Count() == numMipMaps * texData.arraySize);
- SLANG_RETURN_ON_FAIL(uploadTexture.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, uploadResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
-
- uploadTexture.setDebugName(L"TextureUpload");
- }
+ // Sub resource indexing
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/dn705766(v=vs.85).aspx#subresource_indexing
- // Map it all
+ int subResourceIndex = 0;
+ for (int i = 0; i < texData.arraySize; i++)
{
+ // Create the upload texture
+ D3D12Resource uploadTexture;
+ {
+ D3D12_HEAP_PROPERTIES heapProps;
+
+ heapProps.Type = D3D12_HEAP_TYPE_UPLOAD;
+ heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
+ heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
+ heapProps.CreationNodeMask = 1;
+ heapProps.VisibleNodeMask = 1;
+
+ D3D12_RESOURCE_DESC uploadResourceDesc;
+
+ uploadResourceDesc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
+ uploadResourceDesc.Format = DXGI_FORMAT_UNKNOWN;
+ uploadResourceDesc.Width = requiredSize;
+ uploadResourceDesc.Height = 1;
+ uploadResourceDesc.DepthOrArraySize = 1;
+ uploadResourceDesc.MipLevels = 1;
+ uploadResourceDesc.SampleDesc.Count = 1;
+ uploadResourceDesc.SampleDesc.Quality = 0;
+ uploadResourceDesc.Flags = D3D12_RESOURCE_FLAG_NONE;
+ uploadResourceDesc.Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR;
+ uploadResourceDesc.Alignment = 0;
+
+ SLANG_RETURN_ON_FAIL(uploadTexture.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, uploadResourceDesc, D3D12_RESOURCE_STATE_GENERIC_READ, nullptr));
+
+ uploadTexture.setDebugName(L"TextureUpload");
+ }
+
ID3D12Resource* uploadResource = uploadTexture;
uint8_t* p;
uploadResource->Map(0, nullptr, reinterpret_cast<void**>(&p));
+
+ for (int j = 0; j < numMipMaps; ++j)
+ {
+ const D3D12_PLACED_SUBRESOURCE_FOOTPRINT& layout = layouts[j];
+ const D3D12_SUBRESOURCE_FOOTPRINT& footprint = layout.Footprint;
- // Strictly speaking it should be bigger
- assert(texData.dataBuffer.Count() == numMipMaps);
+ int mipWidth = width >> j;
+ mipWidth = (mipWidth <= 0) ? 1 : mipWidth;
+
+ int mipHeight = height >> j;
+ mipHeight = (mipHeight <= 0) ? 1 : mipHeight;
- for (int i = 0; i < texData.arraySize; i++)
- {
- for (int j = 0; j < numMipMaps; ++j)
- {
- int size = texData.textureSize >> j;
+ int mipDepth = depth >> j;
+ mipDepth = (mipDepth <= 0) ? 1 : mipDepth;
- const size_t mipSizeInBytes = layouts[j].Footprint.RowPitch * mipNumRows[j];
+ assert(footprint.Width == mipWidth && footprint.Height == mipHeight && footprint.Depth == mipDepth);
- // NOTE! Like the D3D11 implementation -> this repeats the same mip pixels to every target
+ // NOTE! Like the D3D11 implementation -> this repeats the same mip pixels to every target (!)
+ const List<uint32_t>& srcMip = texData.dataBuffer[j];
- const uint8_t* srcPixels = (const uint8_t*)texData.dataBuffer[j].Buffer();
- assert(mipSizeInBytes == texData.dataBuffer[j].Count() * sizeof(uint32_t));
+ // Check the input data is the same size as expected
+ assert(mipWidth * mipHeight * mipDepth == srcMip.Count());
- ::memcpy(p + layouts[j].Offset, srcPixels, mipSizeInBytes);
- }
- }
- uploadResource->Unmap(0, nullptr);
- }
+ const ptrdiff_t dstMipRowPitch = ptrdiff_t(layouts[j].Footprint.RowPitch);
+ const ptrdiff_t srcMipRowPitch = ptrdiff_t(sizeof(uint32_t) * mipWidth);
- {
- D3D12_HEAP_PROPERTIES heapProps;
+ assert(dstMipRowPitch >= srcMipRowPitch);
+
+ const uint8_t* srcRow = (const uint8_t*)srcMip.Buffer();
+ uint8_t* dstRow = p + layouts[j].Offset;
- heapProps.Type = D3D12_HEAP_TYPE_DEFAULT;
- heapProps.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
- heapProps.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
- heapProps.CreationNodeMask = 1;
- heapProps.VisibleNodeMask = 1;
+ // Copy the depth each mip
+ for (int l = 0; l < mipDepth; l++)
+ {
+ // Copy rows
+ for (int k = 0; k < mipHeight; ++k)
+ {
+ ::memcpy(dstRow, srcRow, srcMipRowPitch);
- SLANG_RETURN_ON_FAIL(resourceOut.initCommitted(m_device, heapProps, D3D12_HEAP_FLAG_NONE, resourceDesc, D3D12_RESOURCE_STATE_COPY_DEST, nullptr));
-
- resourceOut.setDebugName(L"Texture");
- }
+ srcRow += srcMipRowPitch;
+ dstRow += dstMipRowPitch;
+ }
+ }
- {
- for (int i = 0; i < numMipMaps; ++i)
+ assert(srcRow == (const uint8_t*)(srcMip.Buffer() + srcMip.Count()));
+ }
+ uploadResource->Unmap(0, nullptr);
+
+ for (int mipIndex = 0; mipIndex < numMipMaps; ++mipIndex)
{
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/dn903862(v=vs.85).aspx
+
D3D12_TEXTURE_COPY_LOCATION src;
src.pResource = uploadTexture;
src.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
- src.PlacedFootprint = layouts[i];
+ src.PlacedFootprint = layouts[mipIndex];
D3D12_TEXTURE_COPY_LOCATION dst;
dst.pResource = resourceOut;
dst.Type = D3D12_TEXTURE_COPY_TYPE_SUBRESOURCE_INDEX;
- dst.SubresourceIndex = UINT(i);
+ dst.SubresourceIndex = subResourceIndex;
m_commandList->CopyTextureRegion(&dst, 0, 0, 0, &src, nullptr);
+
+ subResourceIndex++;
+ }
+
+ {
+ D3D12BarrierSubmitter submitter(m_commandList);
+ resourceOut.transition(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, submitter);
}
- }
- {
- D3D12BarrierSubmitter submitter(m_commandList);
- resourceOut.transition(D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, submitter);
+ // Block - waiting for copy to complete (so can drop upload texture)
+ submitGpuWorkAndWait();
}
- // Block - waiting for copy to complete (so can drop upload texture)
- submitGpuWorkAndWait();
-
return SLANG_OK;
}
@@ -733,7 +800,7 @@ Result D3D12Renderer::createInputTexture(const InputTextureDesc& inputDesc, D3D1
DXGI_FORMAT pixelFormat = resourceDesc.Format;
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
- _initSrvDesc(resourceDesc, pixelFormat, srvDesc);
+ _initSrvDesc(inputDesc, resourceDesc, pixelFormat, srvDesc);
// Copy to the descriptor
m_device->CreateShaderResourceView(resourceOut, &srvDesc, viewHeap.getCpuHandle(srvIndex));
@@ -746,6 +813,7 @@ Result D3D12Renderer::createInputBuffer(InputBufferDesc& bufferDesc, const List<
D3D12Resource& bufferOut)
{
const size_t bufferSize = bufferData.Count() * sizeof(unsigned int);
+ //bufferSize = D3DUtil::calcAligned(bufferSize, 256);
D3D12_RESOURCE_DESC resourceDesc;
_initBufferResourceDesc(bufferSize, resourceDesc);
@@ -775,36 +843,45 @@ Result D3D12Renderer::createInputBuffer(InputBufferDesc& bufferDesc, const List<
D3D12Resource uploadBuffer;
SLANG_RETURN_ON_FAIL(createBuffer(resourceDesc, bufferData.Buffer(), uploadBuffer, finalState, bufferOut));
- const int elemSize = bufferDesc.stride <= 0 ? 1 : bufferDesc.stride;
+ const int elemSize = bufferDesc.stride <= 0 ? sizeof(uint32_t) : bufferDesc.stride;
- if (bufferDesc.type == InputBufferType::StorageBuffer)
+ if (uavIndex >= 0)
{
- D3D12_UNORDERED_ACCESS_VIEW_DESC viewDesc = {};
+ assert(bufferDesc.type == InputBufferType::StorageBuffer);
- viewDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
- viewDesc.Format = DXGI_FORMAT_UNKNOWN;
+ D3D12_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
- viewDesc.Buffer.FirstElement = 0;
- viewDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize);
- viewDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
+ uavDesc.ViewDimension = D3D12_UAV_DIMENSION_BUFFER;
+ uavDesc.Format = DXGI_FORMAT_UNKNOWN;
+
+ uavDesc.Buffer.StructureByteStride = elemSize;
+
+ uavDesc.Buffer.FirstElement = 0;
+ uavDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize);
+ uavDesc.Buffer.Flags = D3D12_BUFFER_UAV_FLAG_NONE;
if (bufferDesc.stride == 0)
{
// TODO: are there UAV cases we need to handle that are neither
// raw nor structured? RWBuffer<T> would be one...
- viewDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW;
- viewDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+ uavDesc.Buffer.Flags |= D3D12_BUFFER_UAV_FLAG_RAW;
+ uavDesc.Format = DXGI_FORMAT_R32_TYPELESS;
+
+ uavDesc.Buffer.StructureByteStride = 0;
}
- m_device->CreateUnorderedAccessView(bufferOut.getResource(), nullptr, &viewDesc, viewHeap.getCpuHandle(uavIndex));
+ m_device->CreateUnorderedAccessView(bufferOut.getResource(), nullptr, &uavDesc, viewHeap.getCpuHandle(uavIndex));
}
- if (bufferDesc.type != InputBufferType::ConstantBuffer)
+ if (srvIndex >= 0)
{
+ //bufferDesc.type != InputBufferType::ConstantBuffer
+
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srvDesc.Format = DXGI_FORMAT_UNKNOWN;
+ srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Buffer.FirstElement = 0;
srvDesc.Buffer.NumElements = (UINT)(bufferData.Count() * sizeof(unsigned int) / elemSize);
@@ -1091,9 +1168,11 @@ Result D3D12Renderer::calcGraphicsPipelineState(ComPtr<ID3D12RootSignature>& sig
psoDesc.PrimitiveTopologyType = m_primitiveTopologyType;
{
+ const int numRenderTargets = m_boundBindingState ? m_boundBindingState->m_numRenderTargets : 1;
+
psoDesc.DSVFormat = m_depthStencilFormat;
- psoDesc.NumRenderTargets = m_boundBindingState->m_numRenderTargets;
- for (Int i = 0; i < m_boundBindingState->m_numRenderTargets; i++)
+ psoDesc.NumRenderTargets = numRenderTargets;
+ for (Int i = 0; i < numRenderTargets; i++)
{
psoDesc.RTVFormats[i] = m_targetFormat;
}
@@ -1288,23 +1367,7 @@ Result D3D12Renderer::_calcBindParameters(BindParameters& params)
{
int numConstantBuffers = 0;
{
- // Okay we need to try and create a render state
- for (int i = 0; i < int(m_boundConstantBuffers.Count()); i++)
- {
- const BufferImpl* buffer = m_boundConstantBuffers[i];
- if (buffer)
- {
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- D3D12_ROOT_DESCRIPTOR& descriptor = param.Descriptor;
- descriptor.ShaderRegister = numConstantBuffers;
- descriptor.RegisterSpace = 0;
-
- numConstantBuffers++;
- }
- }
if (m_boundBindingState)
{
@@ -1312,68 +1375,86 @@ Result D3D12Renderer::_calcBindParameters(BindParameters& params)
for (int i = 0; i < int(m_boundBindingState->m_bindings.Count()); i++)
{
const Binding& binding = m_boundBindingState->m_bindings[i];
- if (binding.m_type == ShaderInputType::Buffer)
+ if (binding.m_type == ShaderInputType::Buffer && binding.m_bufferType == InputBufferType::ConstantBuffer)
{
- if (binding.m_bufferType == InputBufferType::ConstantBuffer)
- {
- // Make sure it's not overlapping the ones we just statically defined
- assert(binding.m_binding < numBoundConstantBuffers);
+ // Make sure it's not overlapping the ones we just statically defined
+ //assert(binding.m_binding < numBoundConstantBuffers);
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ D3D12_ROOT_PARAMETER& param = params.nextParameter();
+ param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- D3D12_ROOT_DESCRIPTOR& descriptor = param.Descriptor;
- descriptor.ShaderRegister = binding.m_binding;
- descriptor.RegisterSpace = 0;
+ D3D12_ROOT_DESCRIPTOR& descriptor = param.Descriptor;
+ descriptor.ShaderRegister = binding.m_binding;
+ descriptor.RegisterSpace = 0;
- numConstantBuffers++;
- }
+ numConstantBuffers++;
+ }
- if (binding.m_bufferType == InputBufferType::StorageBuffer)
- {
- D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
+ if (binding.m_srvIndex >= 0)
+ {
+ D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
- range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
- range.NumDescriptors = 1;
- range.BaseShaderRegister = binding.m_binding;
- range.RegisterSpace = 0;
- range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
+ range.NumDescriptors = 1;
+ range.BaseShaderRegister = binding.m_binding;
+ range.RegisterSpace = 0;
+ range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
+ D3D12_ROOT_PARAMETER& param = params.nextParameter();
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- D3D12_ROOT_DESCRIPTOR_TABLE& table = param.DescriptorTable;
- table.NumDescriptorRanges = 1;
- table.pDescriptorRanges = &range;
- }
+ D3D12_ROOT_DESCRIPTOR_TABLE& table = param.DescriptorTable;
+ table.NumDescriptorRanges = 1;
+ table.pDescriptorRanges = &range;
+ }
- if (binding.m_uavIndex >= 0)
- {
- D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
+ if (binding.m_uavIndex >= 0)
+ {
+ D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
- range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
- range.NumDescriptors = 1;
- range.BaseShaderRegister = binding.m_binding;
- range.RegisterSpace = 0;
- range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
+ range.RangeType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
+ range.NumDescriptors = 1;
+ range.BaseShaderRegister = binding.m_binding;
+ range.RegisterSpace = 0;
+ range.OffsetInDescriptorsFromTableStart = D3D12_DESCRIPTOR_RANGE_OFFSET_APPEND;
- D3D12_ROOT_PARAMETER& param = params.nextParameter();
+ D3D12_ROOT_PARAMETER& param = params.nextParameter();
- param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
- param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+ param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
+ param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
- D3D12_ROOT_DESCRIPTOR_TABLE& table = param.DescriptorTable;
- table.NumDescriptorRanges = 1;
- table.pDescriptorRanges = &range;
- }
+ D3D12_ROOT_DESCRIPTOR_TABLE& table = param.DescriptorTable;
+ table.NumDescriptorRanges = 1;
+ table.pDescriptorRanges = &range;
}
}
}
}
+#if 1
+ // Okay we need to try and create a render state
+ for (int i = 0; i < int(m_boundConstantBuffers.Count()); i++)
+ {
+ const BufferImpl* buffer = m_boundConstantBuffers[i];
+ if (buffer)
+ {
+ D3D12_ROOT_PARAMETER& param = params.nextParameter();
+ param.ParameterType = D3D12_ROOT_PARAMETER_TYPE_CBV;
+ param.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL;
+
+ D3D12_ROOT_DESCRIPTOR& descriptor = param.Descriptor;
+ descriptor.ShaderRegister = numConstantBuffers;
+ descriptor.RegisterSpace = 0;
+
+ numConstantBuffers++;
+ }
+ }
+#endif
+
+ // All the samplers are in one continuous section of the sampler heap
if (m_boundBindingState && m_boundBindingState->m_samplerHeap.getUsedSize() > 0)
{
D3D12_DESCRIPTOR_RANGE& range = params.nextRange();
@@ -1403,11 +1484,50 @@ Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsC
submitter->setRootSignature(renderState->m_rootSignature);
commandList->SetPipelineState(renderState->m_pipelineState);
+ if (bindingState)
+ {
+ ID3D12DescriptorHeap* heaps[] =
+ {
+ bindingState->m_viewHeap.getHeap(),
+ bindingState->m_samplerHeap.getHeap(),
+ };
+ commandList->SetDescriptorHeaps(SLANG_COUNT_OF(heaps), heaps);
+ }
+ else
+ {
+ commandList->SetDescriptorHeaps(0, nullptr);
+ }
+
{
int index = 0;
int numConstantBuffers = 0;
{
+ if (bindingState)
+ {
+ D3D12DescriptorHeap& heap = bindingState->m_viewHeap;
+
+ for (int i = 0; i < int(bindingState->m_bindings.Count()); i++)
+ {
+ const Binding& binding = bindingState->m_bindings[i];
+ if (binding.m_type == ShaderInputType::Buffer && binding.m_bufferType == InputBufferType::ConstantBuffer)
+ {
+ submitter->setRootConstantBufferView(index++, binding.m_resource.getResource()->GetGPUVirtualAddress());
+ numConstantBuffers++;
+ }
+
+ if (binding.m_srvIndex >= 0)
+ {
+ submitter->setRootDescriptorTable(index++, heap.getGpuHandle(binding.m_srvIndex));
+ }
+
+ if (binding.m_uavIndex >= 0)
+ {
+ submitter->setRootDescriptorTable(index++, heap.getGpuHandle(binding.m_uavIndex));
+ }
+ }
+ }
+
// Okay we need to try and create a render state
for (int i = 0; i < int(m_boundConstantBuffers.Count()); i++)
{
@@ -1420,37 +1540,8 @@ Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsC
::memcpy(cursor.m_position, buffer->m_memory.Buffer(), bufferSize);
// Set the constant buffer
submitter->setRootConstantBufferView(index++, m_circularResourceHeap.getGpuHandle(cursor));
-
- numConstantBuffers++;
- }
- }
-
- if (bindingState)
- {
- D3D12DescriptorHeap& heap = bindingState->m_viewHeap;
-
- for (int i = 0; i < int(bindingState->m_bindings.Count()); i++)
- {
- const Binding& binding = bindingState->m_bindings[i];
- if (binding.m_type == ShaderInputType::Buffer)
- {
- if (binding.m_bufferType == InputBufferType::ConstantBuffer)
- {
- submitter->setRootConstantBufferView(index++, binding.m_resource.getResource()->GetGPUVirtualAddress());
- numConstantBuffers++;
- }
-
- if (binding.m_bufferType == InputBufferType::StorageBuffer)
- {
- submitter->setRootDescriptorTable(index++, heap.getGpuHandle(binding.m_srvIndex));
- }
-
- if (binding.m_uavIndex >= 0)
- {
- submitter->setRootDescriptorTable(index++, heap.getGpuHandle(binding.m_uavIndex));
- }
- }
+ numConstantBuffers++;
}
}
}
@@ -1461,19 +1552,7 @@ Result D3D12Renderer::_bindRenderState(RenderState* renderState, ID3D12GraphicsC
}
}
- if (bindingState)
- {
- ID3D12DescriptorHeap* heaps[] =
- {
- bindingState->m_viewHeap.getHeap(),
- bindingState->m_samplerHeap.getHeap(),
- };
- commandList->SetDescriptorHeaps(SLANG_COUNT_OF(heaps), heaps);
- }
- else
- {
- commandList->SetDescriptorHeaps(0, nullptr);
- }
+
return SLANG_OK;
}
@@ -1550,27 +1629,37 @@ Result D3D12Renderer::initialize(void* inWindowHandle)
return SLANG_FAIL;
}
- UINT adapterCounter = 0;
- for (;;)
+ const bool useWarp = false;
+
+ if (useWarp)
{
- UINT adapterIndex = adapterCounter++;
+ SLANG_RETURN_ON_FAIL(dxgiFactory->EnumWarpAdapter(IID_PPV_ARGS(adapter.writeRef())));
+ SLANG_RETURN_ON_FAIL(D3D12CreateDevice_(adapter, featureLevel, IID_PPV_ARGS(m_device.writeRef())));
+ }
+ else
+ {
+ UINT adapterCounter = 0;
+ for (;;)
+ {
+ UINT adapterIndex = adapterCounter++;
- ComPtr<IDXGIAdapter1> candidateAdapter;
- if (dxgiFactory->EnumAdapters1(adapterIndex, candidateAdapter.writeRef()) == DXGI_ERROR_NOT_FOUND)
- break;
+ ComPtr<IDXGIAdapter1> candidateAdapter;
+ if (dxgiFactory->EnumAdapters1(adapterIndex, candidateAdapter.writeRef()) == DXGI_ERROR_NOT_FOUND)
+ break;
- DXGI_ADAPTER_DESC1 desc;
- candidateAdapter->GetDesc1(&desc);
+ DXGI_ADAPTER_DESC1 desc;
+ candidateAdapter->GetDesc1(&desc);
- if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
- {
- // TODO: may want to allow software driver as fallback
- }
- else if (SUCCEEDED(D3D12CreateDevice_(candidateAdapter, featureLevel, IID_PPV_ARGS(m_device.writeRef()))))
- {
- // We found one!
- adapter = candidateAdapter;
- break;
+ if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
+ {
+ // TODO: may want to allow software driver as fallback
+ }
+ else if (SUCCEEDED(D3D12CreateDevice_(candidateAdapter, featureLevel, IID_PPV_ARGS(m_device.writeRef()))))
+ {
+ // We found one!
+ adapter = candidateAdapter;
+ break;
+ }
}
}
@@ -2155,6 +2244,12 @@ void D3D12Renderer::draw(UInt vertexCount, UInt startVertex)
ID3D12GraphicsCommandList* commandList = m_commandList;
RenderState* renderState = calcRenderState();
+ if (!renderState)
+ {
+ assert(!"Couldn't create render state");
+ return;
+ }
+
BindingStateImpl* bindingState = m_boundBindingState;
// Submit - setting for graphics
@@ -2227,12 +2322,17 @@ BindingState* D3D12Renderer::createBindingState(const ShaderInputLayout& layout)
{
case ShaderInputType::Buffer:
{
- dstEntry.m_uavIndex = bindingState->m_viewHeap.allocate();
- dstEntry.m_srvIndex = bindingState->m_viewHeap.allocate();
-
- if (dstEntry.m_uavIndex < 0 || dstEntry.m_srvIndex < 0)
+ // NOTE! In this arrangement the buffer can either be a ConstantBuffer or a 'StorageBuffer'.
+ // If it's a storage buffer then it has a 'uav'.
+ // In neither circumstance is there an associated srv
+ // This departs a little from dx11 code - in that it will create srv and uav for a storage buffer.
+ if (srcEntry.bufferDesc.type == InputBufferType::StorageBuffer)
{
- return nullptr;
+ dstEntry.m_uavIndex = bindingState->m_viewHeap.allocate();
+ if (dstEntry.m_uavIndex < 0)
+ {
+ return nullptr;
+ }
}
SLANG_RETURN_NULL_ON_FAIL(createInputBuffer(srcEntry.bufferDesc, srcEntry.bufferData, bindingState->m_viewHeap, dstEntry.m_uavIndex, dstEntry.m_srvIndex, dstEntry.m_resource));
@@ -2299,8 +2399,8 @@ void D3D12Renderer::serializeOutput(BindingState* stateIn, const char* fileName)
if (binding.m_resource.getResource())
{
// create staging buffer
-
- size_t bufferSize = D3DUtil::calcAligned(binding.m_bufferLength, 256);
+ //size_t bufferSize = D3DUtil::calcAligned(binding.m_bufferLength, 256);
+ const size_t bufferSize = binding.m_bufferLength;
D3D12_RESOURCE_DESC stagingDesc;
_initBufferResourceDesc(bufferSize, stagingDesc);
diff --git a/tools/render-test/resource-d3d12.h b/tools/render-test/resource-d3d12.h
index a6537a7d7..1de915489 100644
--- a/tools/render-test/resource-d3d12.h
+++ b/tools/render-test/resource-d3d12.h
@@ -108,12 +108,12 @@ struct D3D12ResourceBase
/// True if a resource is set
SLANG_FORCE_INLINE bool isSet() const { return m_resource != nullptr; }
- /// Coercable into ID3D12Resource
+ /// Coercible into ID3D12Resource
SLANG_FORCE_INLINE operator ID3D12Resource*() const { return m_resource; }
/// restore previous state
#if SLANG_ENABLE_CONSERVATIVE_RESOURCE_BARRIERS
- NV_FORCE_INLINE Void restore(Dx12BarrierSubmitter& submitter) { transition(m_prevState, submitter); }
+ SLANG_FORCE_INLINE Void restore(D3D12BarrierSubmitter& submitter) { transition(m_prevState, submitter); }
#else
SLANG_FORCE_INLINE void restore(D3D12BarrierSubmitter& submitter) { SLANG_UNUSED(submitter) }
#endif
@@ -132,9 +132,9 @@ protected:
/// This is protected so as clients cannot slice the class, and so state tracking is lost
~D3D12ResourceBase() {}
- ID3D12Resource* m_resource;
- D3D12_RESOURCE_STATES m_state;
- D3D12_RESOURCE_STATES m_prevState;
+ ID3D12Resource* m_resource; ///< The resource (ref counted)
+ D3D12_RESOURCE_STATES m_state; ///< The current tracked expected state, if all associated transitions have completed on ID3D12CommandList
+ D3D12_RESOURCE_STATES m_prevState; ///< The previous state
};
struct D3D12Resource : public D3D12ResourceBase
diff --git a/tools/render-test/shader-input-layout.h b/tools/render-test/shader-input-layout.h
index c4c3d9d8c..0f5a54326 100644
--- a/tools/render-test/shader-input-layout.h
+++ b/tools/render-test/shader-input-layout.h
@@ -3,70 +3,77 @@
#include "core/basic.h"
-namespace renderer_test
+namespace renderer_test {
+
+enum class ShaderInputType
+{
+ Buffer, Texture, Sampler, CombinedTextureSampler
+};
+
+enum class InputTextureContent
+{
+ Zero, One, ChessBoard, Gradient
+};
+
+struct InputTextureDesc
+{
+ int dimension = 2;
+ int arrayLength = 0;
+ bool isCube = false;
+ bool isDepthTexture = false;
+ bool isRWTexture = false;
+ int size = 4;
+ InputTextureContent content = InputTextureContent::One;
+};
+
+enum class InputBufferType
+{
+ ConstantBuffer, StorageBuffer
+};
+
+struct InputBufferDesc
+{
+ InputBufferType type = InputBufferType::ConstantBuffer;
+ int stride = 0; // stride == 0 indicates an unstructured buffer.
+};
+
+struct InputSamplerDesc
+{
+ bool isCompareSampler = false;
+};
+
+class ShaderInputLayoutEntry
+{
+public:
+ ShaderInputType type;
+ Slang::List<unsigned int> bufferData;
+ InputTextureDesc textureDesc;
+ InputBufferDesc bufferDesc;
+ InputSamplerDesc samplerDesc;
+ bool isOutput = false;
+ int hlslBinding = -1;
+ Slang::List<int> glslBinding;
+};
+
+struct TextureData
+{
+ Slang::List<Slang::List<unsigned int>> dataBuffer;
+ int textureSize;
+ int mipLevels;
+ int arraySize;
+};
+
+class ShaderInputLayout
{
- enum class ShaderInputType
- {
- Buffer, Texture, Sampler, CombinedTextureSampler
- };
- enum class InputTextureContent
- {
- Zero, One, ChessBoard, Gradient
- };
- struct InputTextureDesc
- {
- int dimension = 2;
- int arrayLength = 0;
- bool isCube = false;
- bool isDepthTexture = false;
- bool isRWTexture = false;
- int size = 4;
- InputTextureContent content = InputTextureContent::One;
- };
- enum class InputBufferType
- {
- ConstantBuffer, StorageBuffer
- };
- struct InputBufferDesc
- {
- InputBufferType type = InputBufferType::ConstantBuffer;
- int stride = 0; // stride == 0 indicates an unstructured buffer.
- };
- struct InputSamplerDesc
- {
- bool isCompareSampler = false;
- };
- class ShaderInputLayoutEntry
- {
- public:
- ShaderInputType type;
- Slang::List<unsigned int> bufferData;
- InputTextureDesc textureDesc;
- InputBufferDesc bufferDesc;
- InputSamplerDesc samplerDesc;
- bool isOutput = false;
- int hlslBinding = -1;
- Slang::List<int> glslBinding;
-
- };
+public:
+ Slang::List<ShaderInputLayoutEntry> entries;
+ Slang::List<Slang::String> globalTypeArguments;
+ int numRenderTargets = 1;
+ void Parse(const char * source);
+};
- struct TextureData
- {
- Slang::List<Slang::List<unsigned int>> dataBuffer;
- int textureSize;
- int mipLevels;
- int arraySize;
- };
- void generateTextureData(TextureData & output, const InputTextureDesc & desc);
+void generateTextureData(TextureData & output, const InputTextureDesc & desc);
- class ShaderInputLayout
- {
- public:
- Slang::List<ShaderInputLayoutEntry> entries;
- Slang::List<Slang::String> globalTypeArguments;
- int numRenderTargets = 1;
- void Parse(const char * source);
- };
-}
+} // namespace render_test
#endif \ No newline at end of file
diff --git a/tools/slang-test/main.cpp b/tools/slang-test/main.cpp
index 0f469e8d9..e67db42e4 100644
--- a/tools/slang-test/main.cpp
+++ b/tools/slang-test/main.cpp
@@ -4,10 +4,12 @@
#include "../../source/core/token-reader.h"
#include "../../source/core/slang-result.h"
+#include "../../source/core/slang-string-util.h"
using namespace Slang;
#include "os.h"
+#include "render-api-util.h"
#define STB_IMAGE_IMPLEMENTATION
#include "external/stb/stb_image.h"
@@ -70,6 +72,9 @@ struct Options
// Exclude test that match one these categories
Dictionary<TestCategory*, TestCategory*> excludeCategories;
+
+ // By default we can test against all apis
+ int enabledApis = int(RenderApiFlag::AllOf);
};
Options options;
@@ -188,6 +193,22 @@ Result parseOptions(int* argc, char** argv)
options.excludeCategories.Add(category, category);
}
}
+ else if (strcmp(arg, "-api") == 0)
+ {
+ if (argCursor == argEnd)
+ {
+ fprintf(stderr, "error: expected comma separated list of apis '%s'\n", arg);
+ return SLANG_FAIL;
+ }
+ const char* apiList = *argCursor++;
+
+ SlangResult res = RenderApiUtil::parseApiFlags(UnownedStringSlice(apiList), &options.enabledApis);
+ if (SLANG_FAILED(res))
+ {
+ fprintf(stderr, "error: unable to parse api list '%s'\n", apiList);
+ return res;
+ }
+ }
else
{
fprintf(stderr, "unknown option '%s'\n", arg);
@@ -195,6 +216,13 @@ Result parseOptions(int* argc, char** argv)
}
}
+ {
+ // Find out what apis are available
+ const int availableApis = RenderApiUtil::getAvailableApis();
+ // Only allow apis we know are available
+ options.enabledApis &= availableApis;
+ }
+
// any arguments left over were positional arguments
argCount = (int)((char**)writeCursor - argv);
argCursor = argv;
@@ -636,6 +664,44 @@ void maybeDumpOutput(
fflush(stderr);
}
+// Finds the specialized or default path for expected data for a test.
+// If neither are found, will return an empty string
+String findExpectedPath(const TestInput& input, const char* postFix)
+{
+ StringBuilder specializedBuf;
+
+ // Try the specialized name first
+ specializedBuf << input.outputStem;
+ if (postFix)
+ {
+ specializedBuf << postFix;
+ }
+ if (File::Exists(specializedBuf))
+ {
+ return specializedBuf;
+ }
+
+
+ // Try the default name
+ StringBuilder defaultBuf;
+ defaultBuf.Clear();
+ defaultBuf << input.filePath;
+ if (postFix)
+ {
+ defaultBuf << postFix;
+ }
+
+ if (File::Exists(defaultBuf))
+ {
+ return defaultBuf;
+ }
+
+ // Couldn't find either
+ printf("referenceOutput '%s' or '%s' not found.\n", defaultBuf.Buffer(), specializedBuf.Buffer());
+
+ return "";
+}
+
TestResult runSimpleTest(TestInput& input)
{
// need to execute the stand-alone Slang compiler on the file, and compare its output to what we expect
@@ -1124,12 +1190,19 @@ TestResult runGLSLComparisonTest(TestInput& input)
return kTestResult_Pass;
}
-TestResult runComputeComparisonImpl(TestInput& input, const char * langOption, String referenceOutput)
+
+TestResult runComputeComparisonImpl(TestInput& input, const char * langOption)
{
// TODO: delete any existing files at the output path(s) to avoid stale outputs leading to a false pass
auto filePath999 = input.filePath;
auto outputStem = input.outputStem;
+ const String referenceOutput = findExpectedPath(input, ".expected.txt");
+ if (referenceOutput.Length() <= 0)
+ {
+ return kTestResult_Fail;
+ }
+
OSProcessSpawner spawner;
spawner.pushExecutablePath(String(options.binDir) + "render-test" + osGetExecutableSuffix());
@@ -1211,22 +1284,22 @@ TestResult runComputeComparisonImpl(TestInput& input, const char * langOption, S
TestResult runSlangComputeComparisonTest(TestInput& input)
{
- return runComputeComparisonImpl(input, "-slang -compute", input.outputStem + ".expected.txt");
+ return runComputeComparisonImpl(input, "-slang -compute");
}
TestResult runSlangComputeComparisonTestEx(TestInput& input)
{
- return runComputeComparisonImpl(input, "", input.outputStem + ".expected.txt");
+ return runComputeComparisonImpl(input, "");
}
TestResult runHLSLComputeTest(TestInput& input)
{
- return runComputeComparisonImpl(input, "-hlsl-rewrite -compute", input.outputStem + ".expected.txt");
+ return runComputeComparisonImpl(input, "-hlsl-rewrite -compute");
}
TestResult runSlangRenderComputeComparisonTest(TestInput& input)
{
- return runComputeComparisonImpl(input, "-slang -gcompute", input.outputStem + ".expected.txt");
+ return runComputeComparisonImpl(input, "-slang -gcompute");
}
TestResult doRenderComparisonTestRun(TestInput& input, char const* langOption, char const* outputKind, String* outOutput)
@@ -1411,12 +1484,48 @@ TestResult skipTest(TestInput& /*input*/)
return kTestResult_Ignored;
}
+static bool hasD3D12Option(const TestOptions& testOptions)
+{
+ return (testOptions.args.IndexOf("-dx12") != UInt(-1) ||
+ testOptions.args.IndexOf("-d3d12") != UInt(-1));
+}
+
+bool hasD3D12Option(const FileTestList& testList)
+{
+ const int numTests = int(testList.tests.Count());
+ for (int i = 0; i < numTests; i++)
+ {
+ if (hasD3D12Option(testList.tests[i]))
+ {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool isRenderTest(const String& command)
+{
+ return command == "COMPARE_COMPUTE" ||
+ command == "COMPARE_COMPUTE_EX" ||
+ command == "HLSL_COMPUTE" ||
+ command == "COMPARE_RENDER_COMPUTE" ||
+ command == "COMPARE_HLSL_RENDER" ||
+ command == "COMPARE_HLSL_CROSS_COMPILE_RENDER" ||
+ command == "COMPARE_HLSL_GLSL_RENDER";
+}
+
TestResult runTest(
String const& filePath,
String const& outputStem,
TestOptions const& testOptions,
FileTestList const& testList)
{
+ // If this is d3d12 test
+ if (hasD3D12Option(testOptions) && (options.enabledApis & RenderApiFlag::D3D12) == 0)
+ {
+ return kTestResult_Ignored;
+ }
+
// based on command name, dispatch to an appropriate callback
struct TestCommands
{
@@ -1426,11 +1535,11 @@ TestResult runTest(
static const TestCommands kTestCommands[] =
{
- { "SIMPLE", &runSimpleTest },
- { "REFLECTION", &runReflectionTest },
+ { "SIMPLE", &runSimpleTest},
+ { "REFLECTION", &runReflectionTest},
#if SLANG_TEST_SUPPORT_HLSL
- { "COMPARE_HLSL", &runHLSLComparisonTest },
- { "COMPARE_HLSL_RENDER", &runHLSLRenderComparisonTest },
+ { "COMPARE_HLSL", &runHLSLComparisonTest},
+ { "COMPARE_HLSL_RENDER", &runHLSLRenderComparisonTest},
{ "COMPARE_HLSL_CROSS_COMPILE_RENDER", &runHLSLCrossCompileRenderComparisonTest},
{ "COMPARE_HLSL_GLSL_RENDER", &runHLSLAndGLSLRenderComparisonTest },
{ "COMPARE_COMPUTE", runSlangComputeComparisonTest},
@@ -1623,6 +1732,9 @@ bool testPassesCategoryMask(
return false;
}
+
+
+
void runTestsOnFile(
TestContext* context,
String filePath)
@@ -1643,6 +1755,29 @@ void runTestsOnFile(
return;
}
+ // If dx12 is available synthesize Dx12 test
+ if ((options.enabledApis & RenderApiFlag::D3D12) != 0)
+ {
+ // If doesn't have option generate dx12 options from dx11
+ if (!hasD3D12Option(testList))
+ {
+ const int numTests = int(testList.tests.Count());
+ for (int i = 0; i < numTests; i++)
+ {
+ const TestOptions& testOptions = testList.tests[i];
+ // If it's a render test, and there is on d3d option, add one
+ if (isRenderTest(testOptions.command) && !hasD3D12Option(testOptions))
+ {
+ // Add with -dx12 option
+ TestOptions testOptionsCopy(testOptions);
+ testOptionsCopy.args.Add("-dx12");
+
+ testList.tests.Add(testOptionsCopy);
+ }
+ }
+ }
+ }
+
// We have found a test to run!
int subTestCount = 0;
for( auto& tt : testList.tests )
diff --git a/tools/slang-test/render-api-util.cpp b/tools/slang-test/render-api-util.cpp
new file mode 100644
index 000000000..b8697c54b
--- /dev/null
+++ b/tools/slang-test/render-api-util.cpp
@@ -0,0 +1,210 @@
+
+#include "render-api-util.h"
+
+#include "../../source/core/slang-defines.h"
+
+#include "../../source/core/list.h"
+#include "../../source/core/slang-string-util.h"
+
+/* static */const RenderApiUtil::Info RenderApiUtil::s_infos[] =
+{
+ { RenderApiType::OpenGl, "gl,ogl,opengl"},
+ { RenderApiType::Vulkan, "vk,vulkan"},
+ { RenderApiType::D3D12, "dx12,d3d12"},
+ { RenderApiType::D3D11, "dx11,d3d11"},
+};
+
+static int _calcAvailableApis()
+{
+ int flags = 0;
+ for (int i = 0; i < int(RenderApiType::CountOf); i++)
+ {
+ if (RenderApiUtil::calcHasApi(RenderApiType(i)))
+ {
+ flags |= (1 << i);
+ }
+ }
+
+ return flags;
+}
+
+/* static */int RenderApiUtil::getAvailableApis()
+{
+ static int s_availableApis = _calcAvailableApis();
+ return s_availableApis;
+}
+
+/* static */RenderApiType RenderApiUtil::findApiTypeByName(const Slang::UnownedStringSlice& name)
+{
+ using namespace Slang;
+ List<UnownedStringSlice> namesList;
+ for (int j = 0; j < SLANG_COUNT_OF(RenderApiUtil::s_infos); j++)
+ {
+ const auto& apiInfo = RenderApiUtil::s_infos[j];
+ const UnownedStringSlice names(apiInfo.names);
+
+ if (names.indexOf(',') >= 0)
+ {
+ StringUtil::split(names, ',', namesList);
+ if (namesList.IndexOf(name) != UInt(-1))
+ {
+ return apiInfo.type;
+ }
+ }
+ else if (names == name)
+ {
+ return apiInfo.type;
+ }
+ }
+ return RenderApiType::Unknown;
+}
+
+/* static */int RenderApiUtil::findApiFlagsByName(const Slang::UnownedStringSlice& name)
+{
+ // Special case 'all'
+ if (name == "all")
+ {
+ return int(RenderApiFlag::AllOf);
+ }
+ RenderApiType type = findApiTypeByName(name);
+ return (type == RenderApiType::Unknown) ? 0 : (1 << int(type));
+}
+
+/* static */Slang::Result RenderApiUtil::parseApiFlags(const Slang::UnownedStringSlice& text, int* apiBitsOut)
+{
+ using namespace Slang;
+
+ int apiBits = 0;
+
+ List<UnownedStringSlice> slices;
+ StringUtil::split(text, ',', slices);
+
+ for (int i = 0; i < int(slices.Count()); ++i)
+ {
+ UnownedStringSlice slice = slices[i];
+ bool add = true;
+ if (slice.size() <= 0)
+ {
+ return SLANG_FAIL;
+ }
+ if (slice[0] == '+')
+ {
+ // Drop the +
+ slice = UnownedStringSlice(slice.begin() + 1, slice.end());
+ }
+ else if (slice[0] == '-')
+ {
+ add = false;
+ // Drop the +
+ slice = UnownedStringSlice(slice.begin() + 1, slice.end());
+ }
+
+ // We need to find the bits...
+ int bits = findApiFlagsByName(slice);
+ // 0 means an error
+ if (bits == 0)
+ {
+ return SLANG_FAIL;
+ }
+
+ if (add)
+ {
+ apiBits |= bits;
+ }
+ else
+ {
+ apiBits &= ~bits;
+ }
+ }
+
+ *apiBitsOut = apiBits;
+ return SLANG_OK;
+}
+
+/* !!!!!!!!!!!!!!!!!!!!!!!!!!!! Platform specific stuff !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
+
+
+#if SLANG_WINDOWS_FAMILY
+
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include <Windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#undef NOMINMAX
+
+namespace { // anonymous
+
+class WinModule
+{
+public:
+
+ /// Initialize. Returns the module on success
+ HMODULE init(const char* name)
+ {
+ if (m_module)
+ {
+ ::FreeModule(m_module);
+ m_module = nullptr;
+ }
+ return m_module = ::LoadLibraryA(name);
+ }
+
+ /// convert to HMODULE
+ SLANG_FORCE_INLINE operator HMODULE() const { return m_module; }
+
+ /// True if loaded
+ bool isLoaded() const { return m_module != nullptr; }
+
+ explicit WinModule(const char* name) :
+ m_module(nullptr)
+ {
+ init(name);
+ }
+
+ /// Ctor
+ WinModule() :m_module(nullptr) {}
+ /// Dtor
+ ~WinModule()
+ {
+ if (m_module)
+ {
+ ::FreeLibrary(m_module);
+ }
+ }
+
+protected:
+ HMODULE m_module;
+};
+
+} // anonymous
+
+#else
+#endif
+
+/* static */bool RenderApiUtil::calcHasApi(RenderApiType type)
+{
+#if SLANG_WINDOWS_FAMILY
+ switch (type)
+ {
+ case RenderApiType::OpenGl: return WinModule("opengl32.dll").isLoaded();
+ case RenderApiType::Vulkan: return WinModule("vulkan-1.dll").isLoaded();
+ case RenderApiType::D3D11: return WinModule("d3d11.dll").isLoaded();
+ case RenderApiType::D3D12: return WinModule("d3d12.dll").isLoaded();
+
+ default: return false;
+ }
+
+#else
+
+ switch (type)
+ {
+ case RenderApiType::OpenGl:
+ case RenderApiType::Vulkan:
+ {
+ return true;
+ }
+ default: return false;
+ }
+#endif
+
+}
diff --git a/tools/slang-test/render-api-util.h b/tools/slang-test/render-api-util.h
new file mode 100644
index 000000000..0f941f05d
--- /dev/null
+++ b/tools/slang-test/render-api-util.h
@@ -0,0 +1,61 @@
+#ifndef SLANG_RENDER_API_UTIL_H
+#define SLANG_RENDER_API_UTIL_H
+
+#include "../../source/core/slang-string.h"
+#include "../../source/core/slang-result.h"
+
+
+enum class RenderApiType
+{
+ Unknown = -1,
+ OpenGl = 0,
+ Vulkan,
+ D3D12,
+ D3D11,
+ CountOf,
+};
+
+// Use a struct wrapped Enum instead of enum class, cos we want to be able to manipulate as integrals
+struct RenderApiFlag
+{
+ enum Enum
+ {
+ OpenGl = 1 << int(RenderApiType::OpenGl),
+ Vulkan = 1 << int(RenderApiType::Vulkan),
+ D3D12 = 1 << int(RenderApiType::D3D12),
+ D3D11 = 1 << int(RenderApiType::D3D11),
+ AllOf = (1 << int(RenderApiType::CountOf)) - 1 ///< All bits set
+ };
+};
+
+struct RenderApiUtil
+{
+ struct Info
+ {
+ RenderApiType type; ///< The type
+ const char* names; ///< Comma separated list of names associated with the type
+ };
+
+ /// Returns true if the API is available.
+ static bool calcHasApi(RenderApiType type);
+
+ /// Returns a combination of RenderApiFlag bits which if set indicates that the API is available.
+ static int getAvailableApis();
+
+ /// Returns -1 if unknown
+ static RenderApiType findApiTypeByName(const Slang::UnownedStringSlice& name);
+ /// Returns 0 if none found.
+ static int findApiFlagsByName(const Slang::UnownedStringSlice& name);
+
+ /// Parse api flags string (comma delimited list of api names, or 'all' for all)
+ /// For example "all,-dx12" would be all apis, except dx12
+ static Slang::Result parseApiFlags(const Slang::UnownedStringSlice& text, int* apiBitsOut);
+
+ /// Get information about a render API
+ static const Info& getInfo(RenderApiType type) { return s_infos[int(type)]; }
+
+ /// Static information about each render api
+ static const Info s_infos[int(RenderApiType::CountOf)];
+};
+
+#endif // SLANG_RENDER_API_UTIL_H \ No newline at end of file
diff --git a/tools/slang-test/slang-test.vcxproj b/tools/slang-test/slang-test.vcxproj
index fc4e88493..34d9bed40 100644
--- a/tools/slang-test/slang-test.vcxproj
+++ b/tools/slang-test/slang-test.vcxproj
@@ -160,9 +160,11 @@
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="os.cpp" />
+ <ClCompile Include="render-api-util.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="os.h" />
+ <ClInclude Include="render-api-util.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\source\core\core.vcxproj">
diff --git a/tools/slang-test/slang-test.vcxproj.filters b/tools/slang-test/slang-test.vcxproj.filters
index 3549e6046..e9342cfd6 100644
--- a/tools/slang-test/slang-test.vcxproj.filters
+++ b/tools/slang-test/slang-test.vcxproj.filters
@@ -21,10 +21,16 @@
<ClCompile Include="os.cpp">
<Filter>Source Files</Filter>
</ClCompile>
+ <ClCompile Include="render-api-util.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="os.h">
<Filter>Header Files</Filter>
</ClInclude>
+ <ClInclude Include="render-api-util.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
</ItemGroup>
</Project> \ No newline at end of file