Files
renderdoc/util/test/demos/d3d11/d3d11_workgroup_zoo.cpp
T
Jake Turner 08696443a0 Added workgroup performance tests and basic D3D11 Workgroup test
Added D3D11_Workgroup_Zoo, D3D12 Workgroup Zoo, Vk Workgroup Zoo performance tests

Performance tests primarily for performance testing workgroup debugging speed

Changed workgroup and subgroup result variable from "data" -> "testResult" to help to reduce conflicts
2025-07-21 09:16:56 +01:00

273 lines
7.3 KiB
C++

/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2025 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
#include "3rdparty/fmt/core.h"
#include "d3d11_test.h"
RD_TEST(D3D11_Workgroup_Zoo, D3D11GraphicsTest)
{
static constexpr const char *Description =
"Test of behaviour around workgroup operations in shaders.";
const std::string common = R"EOSHADER(
cbuffer rootconsts : register(b0)
{
uint root_test;
uint root_two;
}
uint GetTest() { return root_test; }
#define IsTest(x) (GetTest() == x)
)EOSHADER";
const std::string compCommon = common + R"EOSHADER(
RWStructuredBuffer<float4> outbuf : register(u0);
static uint3 tid;
static uint flatId;
groupshared uint4 gsmUint4[1024];
void SetOutput(float4 val)
{
outbuf[GetTest() * 1024 + flatId] = val;
}
void Init(float4 val)
{
flatId = tid.x + GROUP_SIZE_X * tid.y + GROUP_SIZE_X * GROUP_SIZE_Y * tid.z;
gsmUint4[flatId].xyz = tid;
gsmUint4[flatId].z = tid.x;
SetOutput(val);
}
)EOSHADER";
const std::string testShader = compCommon + R"EOSHADER(
[numthreads(GROUP_SIZE_X, GROUP_SIZE_Y, 1)]
void main(uint3 inGTid : SV_GroupThreadID)
{
tid = inGTid;
float4 testResult = 0.0f.xxxx;
Init(testResult);
uint id = flatId;
if(IsTest(0))
{
testResult.x = id;
AllMemoryBarrierWithGroupSync();
}
SetOutput(testResult);
}
)EOSHADER";
const std::string perfShader = compCommon + R"EOSHADER(
[numthreads(GROUP_SIZE_X, GROUP_SIZE_Y, GROUP_SIZE_Z)]
void main(uint3 inGTid : SV_GroupThreadID)
{
tid = inGTid;
float4 testResult = 0.0f.xxxx;
Init(testResult);
uint id = flatId;
// TEST CASES:
// 0: GPU math : loops 100
// 1: CPU math : loops 100
// 2: GPU math : loops 200
// 3: CPU math : loops 200
// 4: GPU math : loops 400
// 5: CPU math : loops 400
// 6: GPU math : loops 5000
// 7: CPU math : loops 5000
bool useCpu = GetTest() & 0x1;
uint count = 0;
{
uint temp = GetTest() >> 1;
if(temp == 0)
count = 100U;
if(temp == 1)
count = 200U;
if(temp == 2)
count = 400U;
if(temp == 3)
count = 5000U;
}
if(useCpu)
{
for (uint i = 0; i < count; ++i)
{
gsmUint4[id].x += i;
gsmUint4[id].y += i * i;
testResult.x = testResult.x * testResult.x;
testResult.x += dot(gsmUint4[id], gsmUint4[id]);
}
}
else
{
for (uint i = 0; i < count; ++i)
{
gsmUint4[id].x += i;
gsmUint4[id].y += i * i;
testResult.x = pow(testResult.x, float(root_two));
testResult.x += dot(gsmUint4[id], gsmUint4[id]);
}
}
AllMemoryBarrierWithGroupSync();
SetOutput(testResult);
}
)EOSHADER";
int main()
{
// initialise, create window, create device, etc
if(!Init())
return 3;
ID3D11BufferPtr outBuf = MakeBuffer().Size(sizeof(Vec4f) * 1024).UAV().Structured(sizeof(Vec4f));
ID3D11UnorderedAccessViewPtr outUAV = MakeUAV(outBuf);
int cbufferdata[4];
memset(cbufferdata, 0, sizeof(cbufferdata));
ID3D11BufferPtr cb = MakeBuffer().Size(16).Constant().Data(&cbufferdata);
int32_t countCompTests = 0;
size_t pos = 0;
while(pos != std::string::npos)
{
pos = testShader.find("IsTest(", pos);
if(pos == std::string::npos)
break;
pos += sizeof("IsTest(") - 1;
countCompTests = std::max(countCompTests, atoi(testShader.c_str() + pos) + 1);
}
const int32_t countPerfTests = 8;
struct CompSize
{
int x, y, z;
};
CompSize compsizes[] = {
{70, 1, 1},
};
std::string comppipe_name[ARRAY_COUNT(compsizes)];
ID3D11ComputeShaderPtr testShaders[ARRAY_COUNT(compsizes)];
ID3D11ComputeShaderPtr perfShaders[ARRAY_COUNT(compsizes)];
std::string defines;
for(int i = 0; i < ARRAY_COUNT(compsizes); i++)
{
std::string sizedefine;
sizedefine =
fmt::format("#define GROUP_SIZE_X {}\n#define GROUP_SIZE_Y {}\n#define GROUP_SIZE_Z {}",
compsizes[i].x, compsizes[i].y, compsizes[i].z);
comppipe_name[i] = fmt::format("{}x{}x{}", compsizes[i].x, compsizes[i].y, compsizes[i].z);
testShaders[i] = CreateCS(Compile(defines + sizedefine + testShader, "main", "cs_5_0", true));
perfShaders[i] = CreateCS(Compile(defines + sizedefine + perfShader, "main", "cs_5_0", true));
}
while(Running())
{
ClearRenderTargetView(bbRTV, {0.2f, 0.2f, 0.2f, 1.0f});
pushMarker("Compute Tests");
for(size_t p = 0; p < ARRAY_COUNT(compsizes); p++)
{
pushMarker(comppipe_name[p]);
ctx->CSSetShader(testShaders[p], NULL, 0);
ctx->CSSetUnorderedAccessViews(0, 1, &outUAV.GetInterfacePtr(), NULL);
for(int i = 0; i < countCompTests; ++i)
{
ClearUnorderedAccessView(outUAV, Vec4u());
ctx->UpdateSubresource(cb, 0, NULL, &i, 8, 0);
ctx->CSSetConstantBuffers(0, 1, &cb.GetInterfacePtr());
ctx->Dispatch(2, 1, 1);
popMarker();
}
popMarker();
}
pushMarker("Perf Tests");
for(size_t p = 0; p < ARRAY_COUNT(compsizes); p++)
{
pushMarker(comppipe_name[p]);
ctx->CSSetShader(perfShaders[p], NULL, 0);
ctx->CSSetUnorderedAccessViews(0, 1, &outUAV.GetInterfacePtr(), NULL);
for(int i = 0; i < countPerfTests; ++i)
{
cbufferdata[0] = i;
cbufferdata[1] = 2;
bool useCpu = (i & 0x1);
int count = 0;
{
int temp = i >> 1;
if(temp == 0)
count = 100U;
if(temp == 1)
count = 200U;
if(temp == 2)
count = 400U;
if(temp == 3)
count = 5000U;
}
std::string perfTestName =
fmt::format("{} Iterations {} Math", count, useCpu ? "CPU" : "GPU");
pushMarker(perfTestName);
ClearUnorderedAccessView(outUAV, Vec4u());
ctx->UpdateSubresource(cb, 0, NULL, cbufferdata, 8, 0);
ctx->CSSetConstantBuffers(0, 1, &cb.GetInterfacePtr());
ctx->Dispatch(2, 1, 1);
popMarker();
}
popMarker();
}
popMarker();
Present();
}
return 0;
}
};
REGISTER_TEST();